You are on page 1of 229

AnyBody™ Tutorials PagePage

1Page
of1229
of1 229
of 111

The AnyBody™ Modeling System


AnyBody™ Tutorials
Version 5.0.1, May 2011

Copyright © 2011 AnyBody™ Technology A/S


Home: www.anybodytech.com

mk:@MSITStore:C:\Users\Matthew\Desktop\AnyBody%20Tutorials.chm::/main/main.html 8/29/2011
AnyBody™ Tutorials Page 2 of 229

of the following scenarios:

 Loading a model from the model repository and changing simple parameters like the applied load or the posture. For instance, the so-called StandingModel from the
model repository allows for quick and easy addition of loads to certain predefined points on the model, and the system will compute the muscular reactions.
 Modifying one of the existing motion capture models from the repository to your own lab setup by redefinition of the marker protocol, the force platforms and the
lab coordinate system.
 Modifying a model from the respository with some similarity to what you want. For instance, a normal bicycle model could be changed into a recumbent bike. In this
type of modeling, the user is typically redefining the environment, i.e. non-human, part of the model.
 Constructing a body model and its environment bottom-up. This can be necessary if you want to model an animal or make a detailed model of new type of joint. The
basic steps of such bottom-up model construction are described in the tutorial Getting Started with AnyScript , which is a good place tutorial to complete after this
one, even if you do not plan to build models bottom-up.

These various levels of model building complexity are covered in The Building Block Tutorial in the Making Things Move tutorial.

As you can see above, the more detailed approaches are covered by other tutorials. To get you up and running quickly, we shall take the top-down approach in this tutorial
and use the model repository to accomplish the following:

1. Load the predefined standing model, place it in a given posture, and apply an external force to it.
2. Modify the predefined standing model to carry a hand bag.
3. Create a new model and import a predefined collection of body parts from the library to obtain a model of a simple gymnastics exercise.

This entire tutorial relies heavily on the body model repository. It is a library of predefined models and body parts developed by scientists as a research undertaking and
maintained by AnyBody Technology. A version of the repository compatible with your software version comes with the installation of AnyBody, but you can always find
the newest version of the repository online at the AnyScript Community , which is a free service where e verybody is welcome to contribute. The site is managed jointly
by the AnyBody Research Group and AnyBody Technology A/S with the latter sponsoring the expenses. The direct link to the models is
http://forge.anyscript.org/gf/ .

Before you continue you must unpack the entire repository and save it on your hard disk. A selection of models from the repository are included in the demo collection
which is installed with AnyBody. These demo models should be sufficient for your work with this and other tutorials, but because the repository in continuously updated it
may be a good idea to download and unpack the newest version of the AnyBody Managed Model Repository before you start any serious modeling work.

The demo models, including the Standing Model to be used in this tutorial, are available from the Demo tab of the AnyBody Assistant dialog box.

Scroll down a little and find this link:

Click the link and browse to a location where you want to keep and work on your models, for instance “My Documents\AnyScripts\”. This procedure ensures that it is easy
to reinstall the demo models later, which may be useful when you have been playing around with them for a while; this way you can reset all the changes you have made or
reinstall them to a new location, if you wish to keep your own changes.

With the repository unpacked, let’s take a brief look at its structure. Please open a file manager and navigate to the place you unpacked the repository. You should be able
to discover the following folder structure:

Applications are the models that can be loaded into AnyBody and actually simulate some biomechanical situation, such as cycling, lifting a box or propelling a wheelchair.
Body contains models of body parts and collections of body parts which are used by the applications. For instance, Body includes a lumbar spine model, which is used by
all the applications needing an upper body.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 3 of 229

A closer inspection of the Application branch reveals that it has three sub folders:

The Beta folder contains models that are unfinished but may be of value to users with special interests. The Examples folder contains many models of different situations
and it is very likely that you will be able to find a model similar to what you want to do in it. The Validation folder contains models that have been used for validation
purposes, typically by comparison of the model predictions with experimental measurements.

With that knowledge, you are all set to go, and you can proceed with Lesson 1: Using the standing model .

Lesson 1: Using the standing model


As mentioned in the introduction, the model repository contains many applications in the Examples folder. A few of these are generic in nature and can serve dual
purposes: Either they can be used as they are or with minor modifications or they can be modified and become models of something else. The Standing Model is one of
these general applications, and we shall use it here by virtue of its first ability, i.e. pretty much as it is.

The standing model can be found in the repository under Applications/Examples. The model comprises most of the available body parts in the library. The main file is
called StandingModel.Main.any, and this is the one you must load.

You can open the file with the File->Open menu in AnyBody or by Windows Explorer, but can also you access the more popular demo files through the Demo tab of the
AnyBody Assistant dialog box. After installing the demo models as described in the introduction, the Demo tab will contain links to the more popular example models,
including the Standing Model.

The standing model has a few predefined features and some that you can modify. Here is a short list:

 The model is supported by having both its feet connected to ground. The feet can move with the posture, but they are always supported by the connection with the
floor.
 The posture of the model is controlled via anatomical angles for all major joints except the ankles. The model has a place where these joint angles can be specified
directly. We shall return to this topic shortly.
 The model automatically balances its posture by means of the ankle angles such that its collective center of mass remains vertically above the ankle joints. For
instance, if the model extends the arms in front of it, then the ankles will adjust and move the entire model slightly backwards to maintain the balance.
 The model has a set of predefined points to which can be applied three-dimensional external forces simply defined as spatial vectors. When doing so, the muscles of
the model will be recruited to balance the external forces. However, the ankle angles do not adjust in response to the external forces, so it is possible to apply an
external force large enough to require tension between the feet and the floor. Because of the grounding condition of the feet such a tension will be provided by the
model but the situation may not be realistic because real feet rarely stick to the ground.

It is time to load the model. You do this by pressing the Load Model button in the editor window toolbar or the load model button in the mainframe toolbar:

Reload is a frequent operation for AnyBody users, so the same function has been assigned to function key F7.

After loading is completed, the menu selections Window -> Model View (new) should produce the following result:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 4 of 229

The icons in the toolbar at the top of the Model View window allow you to modify the image, zoom, pan, rotate, etc. They should be mostly self explanatory. Now is a
good time to play a bit around with them and familiarize yourself with the options.

By now you have probably noticed that you can pan, zoom and rotate the model by selecting the appropriate button on the toolbar. In practical use of the system it is often
necessary to change quickly between these functions, so keyboard shortcuts have been provided:

 The Ctrl button activates the Pan function.


 The Shift button activates the Zoom function.
 The Ctrl-Shift combination activates the rotation function.
 If you have a scrolling wheel on your mouse, this will zoom the model in and out.

Depending on the speed of your computer and especially the speed of your graphics card you may experience some delay when you change rotate and pan the model. This
is due to the high level of detail of the model and this delay also applies to other operations you may want to perform. Therefore, it is advantageous to switch off the
muscles as long as we are trying to get the model to do what we want. When it is working correctly we can just switch the muscles back on.

Please go to the editor window and scroll down a little until you get to this place:

// Select the body model:


// ----------------------
// This file contains a list of all body parts, select them to create
// the body model wanted.
#include "BodyPartsSetup.any"

Please double-click the include line. It opens up the BodyPartsSetup file in which you can select which body parts to include and their muscle options. The file contains
segments for each body part, for instance:

// RightArm: 1 included, 0 not included


// ************************************
#define RIGHT_ARM 1
//This is the basic model, following additions available
#define RIGHT_DETAILLED_HAND 0
#define RIGHT_SHOULDER_RHYTHM 0
// This is just the bones,
// Choose one of the following options to add muscles
#define RIGHT_ARM_SIMPLE_MUSCLE 1
#define RIGHT_ARM_SIMPLE_MUSCLE_ONLY_ON_NECK 0
#define RIGHT_ARM_MUS_3E 0

In these definitions, a ‘0’ at the end of a line means that the option is not selected, while a ‘1’ means that it is selected. In the block above, the right arm is included in the
model in a version with a simple hand and no shoulder rhythm, and it is equipped with simple muscles. If you make the following change (marked with red)…

// RightArm: 1 included, 0 not included


// ************************************
#define RIGHT_ARM 1
//This is the basic model, following additions available
#define RIGHT_DETAILLED_HAND 0
#define RIGHT_SHOULDER_RHYTHM 0
// This is just the bones,
// Choose one of the following options to add muscles
#define RIGHT_ARM_SIMPLE_MUSCLE $0$
#define RIGHT_ARM_SIMPLE_MUSCLE_ONLY_ON_NECK 0
#define RIGHT_ARM_MUS_3E 0

…then muscles will be excluded from the right arm. The StandingModel shares this method of setting up the body model with many of the other examples in the
repository.

Please go ahead and set the SIMPLE_MUSCLE option to zero for all the body parts. Then press F7 to reload the model. This time, the reload should be much faster than

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 5 of 229

the first time, and the model view window should update to showing the skeleton without muscles.

This enables us to proceed to Lesson 2: Controlling the posture .

Lesson 2: Controlling the posture


The Standing Model has been set up to have its posture defined by specification of anatomical angles in the joints. These specifications have been collected in one of the
model files, mannequin.any. You can see where this file is included if you scroll down a bit in the StandingModel.any file until you come to this point:

// The Mannequin file specifies load-time positions for all the segments
// in the HumanModel. This is important for the model's ablity to resolve
// all the kinematic constraints when the model is analyzed.
// The mannequin file also drives those degrees of freedom of the human
// model that are not governed by problem-specific drivers at run time.
#include "Mannequin.any"

If you double-click the Mannequin.any file name in the editor window, then the file opens up a new window. The first part of the file contains some logic to handle the fact
that different models have different body parts. Please skip over that and scroll down until you see the following structure (In the interest of legibility we have removed
many of the lines):

AnyFolder Mannequin = {

AnyFolder Posture = {

AnyFolder Right = {
};

AnyFolder Left = {
};
};

AnyFolder PostureVel={

AnyFolder Right = {
};

AnyFolder Left = {
};
};
AnyFolder Load = {

AnyFolder Right = {
};
AnyFolder Left = {
};
}; // Loads

};

This file is typical for the AnyScript language in the sense that it is organized into so-called folders, which is a hierarchy formed by the braces. Each pair of braces delimits
an independent part of the model with its own variables and other definitions.

Everything in this file is contained in the Mannequin folder. It contains specifications of joint angles, movements, and externally applied loads on the body. Each of these
specifications is again subdivided into parts for the right and left hand sides of the body respectively.

The first folder, Posture, contains joint angle specifications. You can set any of the joint angles to a reasonable value (in degrees), and when you reload the model it will
change its posture accordingly. Please make sure that the values are as follows:

AnyFolder Right = {
//Arm
AnyVar SternoClavicularProtraction=-23; //This value is not used for initial position
AnyVar SternoClavicularElevation=11.5; //This value is not used for initial position
AnyVar SternoClavicularAxialRotation=-20; //This value is not used for initial position

AnyVar GlenohumeralFlexion = 0;
AnyVar GlenohumeralAbduction = 10;
AnyVar GlenohumeralExternalRotation = 0;

AnyVar ElbowFlexion = 0.01;


AnyVar ElbowPronation = 10.0;

AnyVar WristFlexion =0;


AnyVar WristAbduction =0;

AnyVar HipFlexion = 0.0;


AnyVar HipAbduction = 5.0;
AnyVar HipExternalRotation = 0.0;

AnyVar KneeFlexion = 0.0;

AnyVar AnklePlantarFlexion =0.0;


AnyVar AnkleEversion =0.0;
};

When these parameters are set for the right hand side, the left hand side automatically follows along and creates a symmetric posture. This happens because each of the
corresponding settings in the Left folder just refers back to the setting in the right folder. The ability to do this is an important part of the AnyScript language: Anywhere a
number is expected, you can write a reference to a variable instead, or even a mathematical expression, if you need it.

If at any time you want a non-symmetric posture, simply replace some of the variable references in the Left folder by numbers of your choice.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 6 of 229

Further down in the Mannequin.any file you find the folder PostureVel. This is organized exactly like Posture, but the numbers you specify here are joint angle velocities in
degrees per second. For now, please leave all the values in this folder to zero.

Finally, the last section of the file is named Load. At this place you can apply three-dimensional load vectors to any of the listed points. These load vectors are in global
coordinates, which means that x is forward, y is vertical, and z is lateral to the right. Let us apply a vertical load to the right hand as if the model was carrying a bag:

AnyFolder Load = {
AnyVec3 TopVertebra = {0.000, 0.000, 0.000};

AnyFolder Right = {
AnyVec3 Shoulder = {0.000, 0.000, 0.000};
AnyVec3 Elbow = {0.000, 0.000, 0.000};
AnyVec3 Hand = {0.000, -50.000, 0.000};
AnyVec3 Hip = {0.000, 0.000, 0.000};
AnyVec3 Knee = {0.000, 0.000, 0.000};
AnyVec3 Ankle = {0.000, 0.000, 0.000};
};
AnyFolder Left = {
AnyVec3 Shoulder = {0.000, 0.000, 0.000};
AnyVec3 Elbow = {0.000, 0.000, 0.000};
AnyVec3 Hand = {0.000, 0.000, 0.000};
AnyVec3 Hip = {0.000, 0.000, 0.000};
AnyVec3 Knee = {0.000, 0.000, 0.000};
AnyVec3 Ankle = {0.000, 0.000, 0.000};
};
}; // Loads

The downward load of -50 N in the right hand roughly corresponds to a weight of 5 kg or 10 lbs. Please reload the model (by pressing F7). If you have done everything
right, you should see the comforting message 'Loaded Successfully' in the message window at the lower left hand side of the AnyBody main frame window. Now it is time
to perform an analysis.

On the left hand side of the screen you find a tall, narrow window with tabs on its left edge. Please select the Operations tab and find the following:

What you see are different operations, i.e. analysis types, the system can perform on the model. Select the InverseDynamics and click the Run button on the toolbar:

You will see the model move slightly into position and and you are finally awarded with the following message:

...Inverse dynamic analysis completed


Total simulation time: 1.593

The standing model has been set up in such a way that when the muscles are removed from the model, they are automatically replaces by joint torque providers with
strengths roughly equivalent to the normal strength of the different degrees of freedom of our joints. So what the analysis has done in the absence of muscles is to compute
the necessary joint torques to balance gravity and the hand load in the posture we have selected.

You have just completed your first analysis of an AnyBody model. In the next lesson we shall briefly examine the results and also see what happens if we ad muscles to the
model: Lesson 3: Reviewing analysis results .

Lesson 3: Reviewing analysis results


AnyBody contains a number of facilities to investigate results of the analysis. One of them is the ChartFX window, which is a standard graphing tool for display of analysis
results. Please click Window -> ChartFX 2D (new). A new window containing a blank field in the middle and a tree view in the left hand pane appears.

The tree expands to reveal the entire structure of output data generated by AnyBody. Every element in the model generates some form of output from the analysis, so the
tree is very large. One of the first nodes you encounter is the MaxMucleActivity variable:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 7 of 229

Clicking the node produces an empty cordinate system in the large field. The reason why it is empty is that the standard setting of the ChartFX View is to display time-
varying data for moving models. In this simple case our model is static, so it does not make much sense to draw curves. Instead we shall switch the setting to Bar diagrams
in by the Gallery button in the toolbar:

You will obtain the following Image:

This tells you that to stand upright and carry the 50 N load in the right hand, the model is using about 13% of its strength. This means that the highest relative load of any
joint in the system is 13.1% the joint’s strength. Even though one number is a very simplified way of regarding a complex biomechanical system, there are good
mathematical reasons why this particular number is a good measure of the human effort of a particular task.

You can obtain more detailed information if you expand the Model branch in the tree view on the left hand side of the bar diagram. Going down through Model ->
HumanModel -> Right -> ShoulderArm -> JointMuscles gives you a list of all the joints in the right shoulder and arm, and inside each joint you can find its corresponding
joint “muscle”. We write “muscle” in quotation marks because it is of course not a real muscle but rather an approximation of the total strength in this joint. Try opening
the FEJnt branch, and you will see it split into an ElbowFlexion and an ElbowPronation part. Proceed to open the ElbowFlexion branch and you get two folders with the
same name except for the capitalization of the letters. The interesting one is the lower case jnt0 folder. Please open it up and see the folder named “Muscle” inside, which
again splits into PosMuscle and NegMuscle. This requires a bit of explanation:

The elbow obviously can do flexion and extension and different anatomical muscles are involved in these movements. This means that the strength in flextion would
normally be different from the strength in extension, and to capture this difference, the joint needs joint torque providers with different strengths for the two directions of
motion. Since the degree-of-freedom is called ElbowFlexion, it is assumed that flexion is the positive direction and extension is negative, and hence the names of the two
“muscles” associated with this joint.

Please open up PosMuscle and click Fm. This will give you the following bar:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 8 of 229

Fm is the muscle force property, which in the case of a joint torque provider is a moment, so the bar indicates that the elbow flexion moment it between 5 and 6 Nm. The
tree contains leaves for all of the joint torque providers in both directions for all degrees-of-freedom of the model, and you can plot bar diagrams just like we did for the
elbow flexion.

But it might be more interesting to work with anatomical muscles. To do this, we need to re-insert the muscles into the model. Please open the BodyPartSetup.any file
again and change ‘0’ back to ‘1’ in all of the “SIMPLE_MUSCLES” lines. Then press F7 again to reload the model. This time you have to wait a bit longer for the load
process because the many muscles take time to process. When loaded, the Model View should automatically change to display the model including the muscles:

Make sure that InverseDynamics is still selected in the operations tree, and click the Run button again. The model will jump into position as it did before and the muscles
will initially stand out from the model but after a few moments fall back into place. The analysis takes more time than before but eventually should finish the “Inverse
dynamic analysis completed” message.

If you study the Model View carefully, you may be able to notice a slight change of color of some of the muscles, for instance the biceps of the right arm. This coloring is
the system’s way of showing the relative load, i.e. the activation level, of each muscle. For models with larger loads, the coloring is more pronounced. Another method of
immediate graphical feedback from the model is muscle bulging. This and other graphical settings can be controlled from a file called DrawSettings.any. You will find it
included at the top of most of the example models in the repository. If you open this file (just double-click the line where it is listed in the editor) then you see different
sections pertaining to the display of different parts of the model. Please make the following changes:

AnyFolder Muscle ={
AnyVec3 RGB = .Colors.AnyBodyRed;
AnySwitch Visible =On;
AnySwitch DrawScaleOnOff =Off;
AnyVar Bulging = $1$;
AnyVar ColorScale =1.0;
AnyVec3 RGBColorScale = {0.957031, 0.785156, 0.785156};
AnyVar MaxStress = $100000$; //N/m^2 //This number is for graphics only!
AnyVar Opacity =1.0;
};

These changes switch the muscle bulging on and also set a bulging factor (MaxStress) that results in visible bulging with the relatively small loads we have applied to this
model. The resulting Model View should look like this:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 9 of 229

Let’s take a look at the actual muscle forces. Please go back to the ChartFX view and browse down its tree to
Main.Study.Output.Model.HumanModel.Right.ShoulderArm.Mus. You will see all of the anatomical muscles in the right arm displayed. A bit down this list you can find
the muscle supraspinatus, which tends to be one of the sources of rotator cuff pain. Like many of the muscles in the model, the anatomical muscle supraspinatus is divided
into several mechanical branches to account for fibers going in different directions and attaching to different bones. If you open op Supraspinatus_3 you can find the
property Fm inside. Click it once, and you should see a new bar illustrating the force in this muscle element similar to the picture below.

This shows that the force in this muscle branch is roughly 10 N. Notice the specification line above the graphics pane marked with the red circle above. This is where the
specification of the current picture is listed. You can use this to plot several muscles at the same time. If you change

Main.Study.Output.Model.HumanModel.Right.ShoulderArm.Mus.supraspinatus_3.Fm

to

Main.Study.Output.Model.HumanModel.Right.ShoulderArm.Mus.supraspinatus_*.Fm

i.e. replace the figure 3 with an asterix, '*', then you should see a bar diagram of all the supraspinatus muscles in the right hand side of the body.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 10 of 229

The use of asterix for specification of multiple muscle forces can be extended even further. If you change the specification line to…

Main.Study.Output.Model.HumanModel.Right.ShoulderArm.Mus.*.Fm

…then you will get a bar diagram of all the muscles in the right shoulder and arm:

The different muscles do indeed have very different forces. You can see the muscle name in a little pop-up window if you hold the mouse still over a given bar.

Congratulations! You have just completed your first biomechanical analysis with the AnyBody Modeling System. Now is a good time to play a bit around with the
facilities of the system and the model. Try changing the posture and/or the load in the mannequin.any file and investigate the results again.

You may also want to check our library of previous webcast for topics of particular interest to you.

Getting started with AnyScript


AnyScript is the model definition language of the AnyBody body modeling system.

AnyScript is actually an object-oriented programming language developed specifically for describing the construction and behavior of bodies of living creatures. It can also
model the different environment components that the body happens to be connected to. Typical examples would be bicycles, furniture, sports equipment, hand tools, and
workplaces.

AnyScript contains facilities for definition of bones (called segments), their connections by joints, muscles, movements, constraints, and exterior forces.

One of the ideas behind AnyScript is that its text-based format and object-oriented structure makes it easy to transfer elements between models. You can build a library of
body segments for use in your different analysis projects, and you can easily exchange models with other users and collaborate with them on complex modeling tasks.

The syntax of AnyScript is much like a Java, JavaScript, or C++ computer program. If you already know one of these programming languages, you will quickly feel at
home with AnyScript. But don't be alarmed if you have no programming experience. AnyScript is very logically constructed, and this tutorial is designed to help new users
getting started as gently as possible.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 11 of 229

So let us take the bull by the horns and get you introduced to the world of body modeling with AnyScript. This tutorial comprises six lessons during which you will
complete your first AnyScript model, a simplified model of an arm.

Each lesson (after lesson 1) begins with a link to a file with the AnyScript code. If you have a problem making your own code work, simply download the file and start
from there.

This tutorial consists of the following lessons:

 Lesson 1: Basic concepts


 Lesson 2: Defining segments and displaying the model
 Lesson 3: Connecting segments by joints
 Lesson 4: Definition of movement
 Lesson 5: Definition of muscles and external forces
 Lesson 6: Adding real bone geometries

Let's get started with Lesson 1: Basic concepts

Lesson 1: Basic concepts


The AnyBody system contains an editor designed for authoring AnyScript files. So the first thing to do is to get AnyBody up and running. Double-click the AnyBody icon,
and you should be greeted by the AnyBody Assistant and behind that an empty workspace.

As you can see, the Main Frame window contains a smaller frame at the bottom. This frame provides much of your interaction with the system once you have a model
running. Notice now in particular the empty rectangular lower portion of the frame. It is the Output Window. The system talks to you through this window. Notice that this
window as well as many other text views in AnyBody can contain active links like in a HTML browser. These links can help you navigate faster around in the system.

As computer software goes, AnyBody is much like any other Computer-Aided Engineering tool. You can create data from scratch, you can read in previously defined data,
and you can exchange data between models. Once you have your data in place, you can perform various actions on it. Let us begin by creating a new AnyScript model. The
menu clicks File -> New Main will bring up a new window in which you can construct your model using the AnyScript language.

The new window is basically a text editor. This main pane of the Editor window will contain the actual AnyScript text. The system has already created the skeleton of a
model for you from a built-in template.

The narrow pane attached to the left side of the Main Frame is a tree view pane, where you find hierarchical representations of the model defined in the text window. If you
are familiar with modern feature-based CAD systems, this idea will be very familar to you. Almost the same tree views are available on the Editor windows containing the
AnyScript code, but they are closed by default. These additional tree views give you the possibility to browse large models in several views at a time. The following tree

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 12 of 229

views are available to you:

 The Model Tree View shows all objects in the model. It is current
 The Operation Tree (only on the Main Frame) shows a subset of the model objects but in the same structural ordering. The objects in this subset are so-called
operations that are the things you can do to the model. An operation can be selected in the Operation Tree and thereafter controlled by the Run, Step, Reset, etc.
buttons below (or on the Main Frame toolbar or the Operations menu). More about operations will follow later.
 The File Tree shows all the files in a model. So far we will only be working with one file, the so-called Main file.

On the Editor windows, you will additionally find some tree views that do not show the objects of the model, but things available to you while modeling.

 The Class Tree shows all the classes in the AnyScript language and it can assist you in inserting the code to create objects.
 The Global and Function Trees show the globally available elements, hereunder functions, in the lanugauge.

So far the Model, the Operation and the File Trees are empty, because the model is not yet loaded into the system. In the upper left corner of the editor you see the little
icon . This means "Script to Model". When you click this icon, the system processes whatever text you have in the editor window and tries to form a valid AnyBody
model. The tree view gets generated and updated this way. A similar button is found in the Main Frame toolbar and the key F7 is a convennient shortcut for this function.

The script to model operation also saves your model files. The first time you save a new file, AnyBody requires you to give your model a name, so clicking the icon
the first time produces a "Save As" dialog.

Let's have a look at what the system has generated for you. If we forget about most of the text and comments, the overall structure of the model looks like this:

Main = {
AnyFolder MyModel = {
}; // MyModel
AnyBodyStudy MyStudy = {
};
}; // Main

What you see is a hierarchy of braces - just like in a C, C++, or Java computer program. The outermost pair of braces is named "Main". Everything else in the model goes
between these braces.

Right now, there are two other sections inside the Main braces: The "AnyFolder MyModel" and the "AnyBodyStudy MyStudy". These are the two basic elements of most
AnyBody models. The term "AnyFolder" is very general. In fact, any pair of braces in AnyScript is a folder. You can think of a folder as a directory on your hard disk. A
directory can contain other directories and files. It's exactly the same with folders. They can contain other folders and elements of the model. The "AnyFolder MyModel" is
the folder containing the entire model you are going to build. The name "MyModel" can be changed by you to anything you like. In fact, let's change it to ArmModel (in
the forthcoming AnyScript text we'll highlight each change by red. Just type the new name into the file, and don't forget to also change other occurrences of MyModel to
ArmModel in the file.

Notice the prefix "Any". All reserved words in AnyScript begin with "Any". This way you can distinguish the elements that belong to the system from what the user
defines. Another way of recognizing reserved words is by virtue of their color in the editor. Class names are recognized by the editor as soon as you type them and colored
blue.

It must be emphasized that AnyScript is case sensitive.

There is more to an AnyScript file than the model. Once you have a model, you can perform various operations on it. These operations are often collected in "studies", and
the "AnyBodyStudy MyStudy" is indeed such a study. You can think of a study as the definition of a task or set of tasks to perform. The study also contains methods to
perform the tasks. The Study of Studies tutorial contains much more information about these subjects. For now, let's just rename "MyStudy" to "ArmModelStudy".

Let's look a little closer at the contents of what is now the ArmModel folder:

// The actual body model goes in this folder


AnyFolder ArmModel = {
// Global Reference Frame
AnyFixedRefFrame GlobalRef = {
// Todo: Add points for grounding
// of the model here
}; // Global reference frame
// Todo. Add the model elements such as
// segments, joints, and muscles here.
}; // ArmModel

Most of what you see above is just comments. It is always useful to add lots of comments to your models. Notice that one-line comments are started with //. Multiple-line
comments are enclosed in /* */ just like you may know it from C++ or the Java language. Notice also that lines are terminated by semicolon ';'. Even the lines with closing
braces must be terminated by a semicolon. If you do no terminate with a semicolon, then the statement continues on the next line. You can comment and uncomment a
block of lines in one click by means of the buttons at the top of the Editor window.

The only actual model element in the ArmModel is the declaration of the "AnyFixedRefFrame GlobalRef". All models need a reference frame - a coordinate system - to
work in, so the system has created one for you.

An AnyFixedRefFrame is a predefined data type you can use when you need it. What you have here is the definition of an object of that type. The object gets the name
"GlobalRef", and we can subsequently refer to it anywhere in the ArmModel by that name.

You will notice that there is a "to do" comment inside the braces of this reference frame suggesting that you add points for grounding the model. Don't do it just yet. We
will return to this task later.

But here's an important notice: Everything you define in this tutorial from now on is part of the ArmModel folder and should go between its pair of braces. If you define
something outside these braces that should have been inside, then the necessary references between the elements of the model will not work.

What you have here is actually a valid AnyScript model, although it is empty and cannot do much. If you have typed everything correctly, then you should be able to press
the icon and get the messages

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 13 of 229

Loading Main : "C:\...\NewModel1.any"


Scanning...
Parsing...
Constructing model tree...
Linking identifiers...
Evaluating constants...
Configuring model...
Evaluating model...
Loaded successfully.
Elapsed Time : 0.063000

in the Output Window. But what happens if you mistype something? If your typo leads to a syntactical error, then it will be found by the AnyBody system when it parses
the file, and instead of the "AnyScript loaded successfully", you will get an impolite message that something is wrong. A common mistake is to forget a semicolon
somewhere. Try removing the last semicolon in the AnyScript file, and load again. You get a message saying something like:

ERROR(SCR.PRS11) : C:\...\NewModel1.any(27) : 'EOF' unexpected


Model loading skipped

We now assume that you have removed eventual errors and have loaded the model successfully.

If you are up to it, let's continue onward to Lesson 2: Segments .

This is a typical error message. First there is a message ID, then a file location and finally the body of the message. The former two are written in blue ink and underlined
to show the underlying active links. The file location is the line where the bug was found by the system. If you double-click this link, the cursor in the Editor Window
jumps to the location of the error. Notice that this is where the system found the error, but the error can sometimes be caused by something you mistyped earlier in the file
so that you actually have to change something elsewhere in your model. If you are in doubt of what the error message means, try clicking the error number ERROR
(SCR.PRS11). This will give you a little pop-up window with a more complete explanation:

Lesson 2: Defining segments and displaying objects


Here's an AnyScript file to start on if you have not completed the previous lesson:
demo.lesson2.any

There are some elements that must be present in a body model for it to make any sense at all. The first one is segments. They are the rigid elements of the body that move
around when the model does its stuff. When modeling a human or other higher life form, they usually correspond to the bones of the body. However, they can also be used
to model machines, tools, and other things that might be a part of the model but do not belong to the human body. Hence the more general term "segment"*.

A segment is really nothing but a frame of reference that can move around in space and change its orientation. It has an origin where its center of mass is assumed to be
located, and it has axes coinciding with its principal inertia axes.

We shall start by defining a folder for the segments. Please add the following text to your model (new text marked by red):

// The actual body model goes in this folder


AnyFolder ArmModel = {
// Global Reference Frame
AnyFixedRefFrame GlobalRef = {
// Todo: Add points for grounding
// of the model here
}; // Global reference frame
// Segments
AnyFolder Segs = {
}; // Segs folder
}; // ArmModel

Did you notice that the word AnyFolder turned blue as soon as you typed its last letter? If it did not, you have mistyped something. Try loading the model by clicking the
icon (or pressing F7). If you expand the ArmModel branch in the tree view, you should see a new, empty branch named Segs. It is the new folder you just defined. We
are now ready to add a segment to the model, and this would probably be a good time to introduce you to the object inserter.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 14 of 229

If you look at the left hand side of the tree view in the editor window, you will notice tabs running down the vertical edge. The tabs give you access to different tree views
or let you close the tree view completely if you would rather use the space for something else. One of the tabs is called "Classes" and it produces a tree that has two
branches at its root. Both of these branches contain all the predefined classes in AnyScript. In the first branch, "ClassTree", the classes are ordered hierarchically. This
reflects the object-oriented idea that classes inherit properties from each other. This might be a way of locating a class with particular properties if you are not sure of the
class name.

The other branch, "Class List", simply contains an alphabetical list of all the classes. This is useful if you know the name of the class you are looking for. Try opening each
of the two trees and look for the class AnySeg. Then make sure the cursor in the editor window is located inside the newly defined AnyFolder Segs. Finally, right-click the
AnySeg class name in the tree and choose "Insert Class Template". You should get this:

// Segments
AnyFolder Segs = {
AnySeg <ObjectName> =
{
//r0 = {0, 0, 0};
//rDot0 = {0, 0, 0};
//Axes0 = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
//omega0 = {0, 0, 0};
Mass = 0;
Jii = {0, 0, 0};
//Jij = {0, 0, 0};
//sCoM = {0, 0, 0};
};
}; // Segs folder

The object inserter has created a template of a segment for you. It contains all the properties you can set for an AnySeg object. Some of them are active while other are
commented out by two leading slashes. The ones that are commented out are optional properties. You can set them if you like, but if you leave them out they will retain the
values already indicated in the inserted lines. If you do not plan on using them, you can erase them. The object properties without leading slashes are those that must be set.
This is the case for Mass and Jii, for instance, which are respectively the mass of the segment and the diagonal elements of the inertia tensor. In a system that simulates
dynamics, all segments must have mass and inertia. The system allows you to set them to zero, but it does not make sense not to set them at all.

More formally, object properties are divided into three different groups:

 Obligatory. Like Mass and Jii, these must be set by the user when the object is defined
 Access denied. These are computed automatically by the system and cannot be specified by the user.
 Optional. These can be set by the user or left to their default values.
You can find a complete description of all possible properties of all objects in the reference manual .

Let us give the new segment the name UpperArm and set its Mass = 2 and also assign reasonable values for Jii:

AnySeg UpperArm = {
//r0 = {0, 0, 0};
//Axes0 = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
Mass = 2;
Jii = {0.001, 0.01, 0.01};
}; //UpperArm

Click again (or press F7). Among the messages you get are:

Model Warning: Study 'Main.ArmStudy' contains too few kinematic constraints to be kinematically determinate.

Don't worry about it just now. It only means that you are not finished with the necessary elements to do an actual analysis yet.

Now that we have a physical object in the model, let's see what it looks like. To make something visible in AnyBody, you have to add a line that defines visibility:

AnySeg UpperArm = {
//r0 = {0, 0, 0};
//Axes0 = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
Mass = 2;
Jii = {0.001, 0.01, 0.01};
AnyDrawSeg drw = {};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 15 of 229

}; // UpperArm

Reload the model, and then choose the menus Window -> Model View (new). This opens a graphics window and displays what looks like a long yellow ellipse. On the
toolbar at the top of the graphics window, click the rotation icon . Then click inside the graphics field and drag the mouse in some direction. This causes the yellow
ellipse to rotate, and you will see that it is actually an ellipsoid with a coordinate system through it. If you entered the inertia properties in the Jii specification as written
above, then your ellipsoid should be ten times as long as it is wide. Try changing the "0.001" to "0.01" and reload. The ellipsoid becomes spherical. The dimensions of the
ellipsoid are scaled this way to fit the mass properties of the segment you are defining. It is best to change Jii back to {0.001,0.01,0.01} again.

As you can see, Jii is a vector. If you know your basic mechanics, you may wonder why it is not a 3 x 3 matrix. The reason is that Jii only contains the diagonal members
(the moments of inertia), which is all you need to specify if your segment-fixed reference frame is aligned with the principal axes. If not, the off-diagonal elements (the
deviation moments) can be specified in a property called Jij, which by default contains zeros.

We are eventually going to attach things like muscles, joints, external loads, and visualization objects to our segments. To this end we need attachment points. They are
defined in the local coordinate system of the segment. For a given body part it may be a laborious and difficult task to sort out the correct points. Fortunately, good people
have done much of the work for you, and, if you construct your model wisely, you can often grab most of what you need from models defined by other people. For now, let
us assume that you have sorted out the coordinates of all the points you need on UpperArm, and that you are ready to start adding them. Rather than going through the drill
with the object inserter, you can copy and paste the following lines:

AnySeg UpperArm = {
//r0 = {0, 0, 0};
//Axes0 = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
Mass = 2;
Jii = {0.001, 0.01, 0.01};
AnyDrawSeg drw = {};

AnyRefNode ShoulderNode = {
sRel = {-0.2,0,0};
};
AnyRefNode ElbowNode = {
sRel = {0.2,0,0};
};
AnyRefNode DeltodeusA = {
sRel = {-0.1,0,0.02};
};
AnyRefNode DeltodeusB = {
sRel = {-0.1,0,-0.02};
};
AnyRefNode Brachialis = {
sRel = {0.1,0,0.01};
};
AnyRefNode BicepsShort = {
sRel = {-0.1,0,0.03};
};
AnyRefNode Brachioradialis = {
sRel = {0.05,0,0.02};
};
AnyRefNode TricepsShort = {
sRel = {-0.1,0,-0.01};
};
}; // UpperArm

Try loading the model again and have a look at the graphical representation. If you zoom out enough, you should see your points floating
around the ellipsoid connected to its center of gravity by yellow pins.

One segment does not make much of a mechanism, so let's define a forearm as well. In the segs folder, add these lines:

AnySeg ForeArm = {
Mass = 2.0;
Jii = {0.001,0.01,0.01};
AnyRefNode ElbowNode = {
sRel = {-0.2,0,0};
};
AnyRefNode HandNode = {
sRel = {0.2,0,0};
};
AnyRefNode Brachialis = {
sRel = {-0.1,0,0.02};
};
AnyRefNode Brachioradialis = {
sRel = {0.0,0,0.02};
};
AnyRefNode Biceps = {
sRel = {-0.15,0,0.01};
};
AnyRefNode Triceps = {
sRel = {-0.25,0,-0.05};
};
AnyDrawSeg DrwSeg = {};
}; // ForeArm
}; // Segs folder

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 16 of 229

When you reload the model you may not be able to see that the forearm has been added. In fact it is there, but it is placed exactly on top of the upper arm and since the two
segments have similar mass properties, it is impossible to see which is which.

Before we proceed it might be worth thinking a bit about why objects get placed the way they do in the model and how we can control the placement. The first thing to
notice is that we are in the process of making a model of a living organism which supposedly will move about changing its position all the time. So there really is no "right"
placement of a segment in the model. The second thing to notice is that even if we are able to exercise some control over the placement of objects, then at least we have not
done so yet. So this is why the system for lack of better information places both segments at the origin of the global reference frame at load time.

What eventually will happen is that we will define joints to constrain the segments with respect to each other and also drivers to specify how the mechanism will move.
When all that is done, these specifications will determine where everything is at every point in time. But we need to go through several steps of definitions and
subsequently the system must do some equation solving before everything can fall into its "right" position. So what to do in the meantime? Well, perhaps you noticed that
the UpperArm segment we originally created with the object inserter has two properties named r0 and Axes0. These two properties determine the location and orientation
of the segment at load time. The r0's are easy because they are simply three-dimensional coordinates in space. So we can separate the two segments at load time like this:

AnySeg UpperArm = {
r0 = {0, 0.3, 0};
//Axes0 = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
Mass = 2;
Jii = {0.001, 0.01, 0.01};
AnyDrawSeg drw = {};

and

AnySeg ForeArm = {
r0 = {0.3, 0, 0};
Mass = 2.0;
Jii = {0.001,0.01,0.01};

This will clearly separate the segments in your model view:

So far so good. But it might improve the visual impression if the were also oriented a bit like we would expect an arm to be. This involves the Axes0 property, which is
really a rotation matrix. Such matrices are a bit difficult to cook up on the fly. The predefined version in the UpperArm segment looks like this:

AnySeg UpperArm = {
r0 = {0, 0.3, 0};
Axes0 = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};

If your spatial capacity is really good, you can start figuring out unit vectors for the coordinate system orientation you want and insert them into the Axes0 specification
instead of the existing ones. But there is an easier solution: AnyScript has a standard function named RotMat, which returns a rotation matrix corresponding to a given axis
and rotation angle. Therefore, we can specify:

AnySeg UpperArm = {
r0 = {0, 0.3, 0};
Axes0 = RotMat(-90*pi/180, z);

When you reload again you will see that the UpperArm is indeed rotated -90 degrees about the z axis as the function arguments indicate. Notice the multiplication of the
angle by pi/180. AnyBody identifies the word "pi" as 3.14159... and dividing this with 180 gives the conversion factor between degrees and radians. Angles in AnyScript
are always in radians, but anywhere a number is expected you can substitute it by a mathematical expression just like in other programming languages.

In the next section we will look at how joints can be used to constrain the movement of segments and allow them to articulate the way we desire. So if you are up to it, let's
continue onward to Lesson 3: Connecting segments by joints .

--------------------------------
*In rigid body dynamics terminology, a "segment" would be called a "rigid body", but to avoid unnecessary confusion between the rigid bodies and the total body model,
we have chosen to use "segments" for the rigid parts of the model.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 17 of 229

Lesson 3: Connecting segments by joints


Here's an AnyScript file to start on if you have not completed the previous lesson:
demo.lesson3.any .

You can think of joints in different ways. We tend to perceive them as providers of freedom, which is correct compared to a rigid structure. However in dynamics it is often
practical to perceive joints to be constraining movement rather than releasing it. Two segments that are not joined (constrained) in any way have 2 x 6 = 12 degrees of
freedom. When you join them, you take some of these degrees of freedom away. The different joint types distinguish themselves by the degrees of freedom they remove
from the connected segments.

A segment without joints is basically floating free in space. When you connect the segments by joints, you bind them together in some sense. But the mechanism as a
whole can still fly around in space.

Not knowing where stuff is in space can be very impractical so the first thing to do is usually to ground the mechanism somewhere. Perhaps you remember that the system
added these lines somewhere in the top of the AnyScript model:

AnyFixedRefFrame GlobalRef = {
// Todo: Add points for grounding
// of the model here
}; // Global reference frame

This is actually the definition of a global reference frame of the model. You can think of it as a coordinate system fixed somewhere in global space. Otherwise, it is just like
a segment in the sense that we can add points to it for attachment of joints and muscles. Let’s do just that. Again you can insert the objects with the object inserter or to
save time simply cut and paste the following lines into your model:

AnyFixedRefFrame GlobalRef = {
AnyDrawRefFrame DrwGlobalRef = {};
AnyRefNode Shoulder = {
sRel = {0,0,0};
};
AnyRefNode DeltodeusA = {
sRel = {0.05,0,0};
};
AnyRefNode DeltodeusB = {
sRel = {-0.05,0,0};
};
AnyRefNode BicepsLong = {
sRel = {0.1,0,0};
};
AnyRefNode TricepsLong = {
sRel = {-0.1,0,0};
};
}; // Global reference frame

The first line, "AnyDrawRefFrame ..." does nothing else than cause the global reference system to be displayed in the graphics window. If for some reason you don't want
the reference frame to be visible, just erase this line or make it a comment by prefixing it with "//". It is often nice to have a visualization of the global reference frame, but
the current version may be a bit on the large side for the model. Let us reduce the size a little bit and change the color to better distinguish it from the yellow segments:

AnyDrawRefFrame DrwGlobalRef = {
ScaleXYZ = {0.1, 0.1, 0.1};
RGB = {0,1,0};
};

The remaining lines are definitions of points in the global reference frame.

Now that we have the necessary points available, we can go ahead and fix the upper arm to the global reference frame by means of a "shoulder" joint. A real shoulder is a
very complex mechanism with several joints in it, but for this 2-D model, we shall just define a simple hinge. We create a new folder to contain the joints and define the
shoulder:

}; // LowerArm
}; // Segs folder
AnyFolder Jnts = {
//---------------------------------
AnyRevoluteJoint Shoulder = {
Axis = z;
AnyRefNode &GroundNode = ..GlobalRef.Shoulder;
AnyRefNode &UpperArmNode = ..Segs.UpperArm.ShoulderNode;
}; // Shoulder joint
}; // Jnts folder

A hinge is technically called a revolute joint, and this is what the type definition "AnyRevoluteJoint" means. After that, the definition is just a matter of setting the
properties of the joint that make it behave the way we want. Let's have a closer look at each property:

Axis = z;

The AnyBody system is inherently three-dimensional. This applies also when we are creating a model that will only operate in two dimensions, and it means that a revolute
joint must know which axis to rotate about. The property Axis = z simply specifies that the segment will rotate about the z axis of the node at the joint. Does that sound
complicated?

Well, a segment is really a reference frame. The nodes on segments are also reference frames, and each reference frame can have its orientation defined by the user. A joint
of this type forces the two z axes of the two joined nodes to be parallel. You can control the mutual orientation of the two joined segments by rotating the reference frames
of the nodes you are connecting. This is relevant if you want one of the joints to rotate about some skew axis.

The joint connects several segments, and it needs to know which point on each segment to attach to. For this purpose, we have lines like

AnyRefNode &GroundNode = ..GlobalRef.Shoulder;


AnyRefNode &UpperArmNode = ..Segs.UpperArm.ShoulderNode;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 18 of 229

The simple explanation is that these lines define nodes on the GlobalRef and UpperArm to which the joint attaches. Notice the two dots in front of the names. They signify
that the GlobalRef and Segs folders are defined two levels up compared to where we are now in the model. If you neglected the two dots, then AnyBody would be
searching for the two objects in the Shoulder folder, and would not be able to find them. This "dot" system is quite similar to the system you may know from directory
structures in Dos, Windows, Unix, or just about any other computer operating system.

But there is more to it than that. You can see that the Shoulder point on GlobalRef has been given the local name of "GroundNode". This means that, within the context of
this joint, we can hereafter refer to the point as "GroundNode". This is practical because it allows us to assign shorter names to long external references.

Another specialty is the '&' in front of the local name. If you have C++ experience, you should be familiar with this. It means that GroundNode is a reference (a pointer) to
GlobalRef.Shoulder rather than a copy of it. So if GlobalRef.Shoulder moves around, Shoulder.GroundNode follows with it. Hit F7 to load the model again to make sure
that the definition is correct.

We need an elbow joint before we are finished: the elbow. The definition is completely parallel to what you have just seen, but we shall use one of the handy tools to define
the references. The skeleton of the elbow joint is as follows:

AnyFolder Jnts = {
//---------------------------------
AnyRevoluteJoint Shoulder = {
Axis = z;
AnyRefNode &GroundNode = ..GlobalRef.Shoulder;
AnyRefNode &UpperArmNode = ..Segs.UpperArm.ShoulderNode;
}; // Shoulder joint
AnyRevoluteJoint Elbow = {
Axis = z;
AnyRefNode &UpperArmNode = ;
AnyRefNode &ForeArmNode = ;
}; // Elbow joint
}; // Jnts folder

As you can clearly see, the nodes in the Elbow joint are not pointing at anything yet. In this simple model it is easy to find the relative path of the pertinent nodes on the
upper arm and the forearm, but in a complex model it can be very difficult to sort these references out. So the system offers a tool to help you. If you click the model tab in
the tree view on the left hand side of the editor window, then the tree of objects in the loaded model appears. Anything that was defined in the model when it was recently
successfully loaded can be found in this tree including the two nodes we are going to connect in the elbow. Click to place the cursor just before the semicolon in the
&UpperArmNode definition in the Elbow joint. Then expand the tree as shown below.

When you right-click the ElbowNode you can select "Insert object name" from the context menu. This writes the full path of the node into the Elbow joint definition where
you placed the cursor. Notice that this method inserts the absolute and not the relative path. Repeat the process to expand the ForeArm segment and insert its ElbowNode in
the line below to obtain this:

AnyRevoluteJoint Elbow = {
Axis = z;
AnyRefNode &UpperArmNode = Main.ArmModel.Segs.UpperArm.ElbowNode;
AnyRefNode &ForeArmNode = Main.ArmModel.Segs.ForeArm.ElbowNode;
}; // Elbow joint

Seems like everything is connected now. So why do we still get the annoying error message:

Model Warning: Study 'Main.ArmStudy' contains too few kinematic constraints to be kinematically determinate.

when we reload the model? The explanation is that we have connected the model but we have not specified its position yet. Each of the two joints can still take any angular
position, so there are two degrees of freedom left to specify before AnyBody can determine the mechanism's position. This is taken care of by kinematic drivers.

They are one of the subjects of Lesson 4: Definition of movement .

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 19 of 229

Lesson 4: Definition of movement


Here's an AnyScript file to start on if you have not completed the previous lesson: demo.lesson4.any .

If you have completed the three previous lessons, you should have a model with an upper arm grounded at the shoulder joint and connected to a
forearm by the elbow. What we want to do now is to make the arm move.

How can an arm with no muscles move? Well, in reality it cannot, but in what we are about to do here, the movement comes first, and the muscle forces afterwards. This
technique is known as inverse dynamics. We shall get to the muscles in the next lesson and stick to the movement in this one.

Our mechanism has two degrees of freedom because it can rotate at the shoulder and at the elbow. This means that we have to specify two drivers. The natural way is to
drive the shoulder and elbow rotations directly and this is in fact what we shall do. But we could also choose any other two measures as long as they uniquely determine the
position of all the segments in the mechanism. If you were building this model for some ergonomic investigation, you might want to drive the end point of the forearm
where the wrist should be located in x and y coordinates to simulate the operation of some handles or controls. And this would be just as valid a model because the end
point position uniquely determines the elbow and shoulder rotations.

For now, let's make a new folder and define two drivers:

}; // Jnts folder
AnyFolder Drivers = {
//---------------------------------
AnyKinEqSimpleDriver ShoulderMotion = {
AnyRevoluteJoint &Jnt = ..Jnts.Shoulder;
DriverPos = {-100*pi/180};
DriverVel = {30*pi/180};
}; // Shoulder driver

//---------------------------------
AnyKinEqSimpleDriver ElbowMotion = {
AnyRevoluteJoint &Jnt = ..Jnts.Elbow;
DriverPos = {90*pi/180};
DriverVel = {45*pi/180};
}; // Elbow driver
}; // Driver folder

This is much like what we have seen before. The folder contains two objects: ShoulderMotion and ElbowMotion. Each of these are of type AnyKinEqSimpleDriver. A
driver is really nothing but a mathematical function of time. The AnyKinEqSimpleDriver is a particularly simple type that starts at some position at time = 0 and increases
or decreases at constant velocity from there. These two drivers are attached to joints, and therefore they drive joint rotations, but the same driver type could be used to drive
any other degree of freedom as well, for instance the Cartesian position of a point.

The lines

AnyRevoluteJoint &Jnt = ..Jnts.Shoulder;

and

AnyRevoluteJoint &Jnt = ..Jnts.Elbow;

are the ones that affiliate the two drivers with the shoulder and elbow joints respectively. They are constructed the same way as the joint definition in Lesson 3 in the sense
that a local variable, Jnt, is declared and can be used instead of the longer global name if we need to reference the joint somewhere else inside the driver. Notice also the
use of the reference operator '&' that causes the local variable to be a pointer to the global one rather than a copy. It means that if some property of the globally defined
joint changes, then the local version changes with it.

The specifications of DriverPos and DriverVel are the starting value of the driver and the constant velocity, respectively. Since these drivers drive angles, the units are
radians and radians/sec.

Try loading the model again by hitting F7. If you did not mistype anything, you should get the message "Loaded successfully" and no complaints about lacking kinematic
constraints this time.

This is good news, because you are now actually ready to see the model move. If you look closer at the pane in the bottom of the main frame, you will notice that it now
contains the root of a tree in its upper left cell. This is the place where the AnyBody system places your studies, and from this window you can execute them, i.e., start
analyses and calculations.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 20 of 229

Try expanding the ArmStudy root. You will get a list of the study types that the system can perform. "Study" is a common name for operations
you can perform on a model. When you click one of the studies, the buttons on the middle, lower part of the panel come to life. Try clicking the KinematicAnalysis study.
With the buttons, you can now execute various types of analysis. The panel contains three buttons:

 Run . This button starts the highlighted study and runs it until the end, usually producing some sort of motion in the model. When Run has been pushed, it changes
name to Break. If you push it in this state, it pauses the running operation. F5 is a shortcut to this function to Run and Break.
 Step . This button advances the operation one step. What a step is depends on the type of operation, but it is typically a time step in a dynamic analysis. (F6 is the
shortcut key for Stepping)
 Reset . This puts the operation back to its initial position. You must reset before you can start a new analysis, if you have stopped it in the middle. (F4 is the shortcut
for resetting operations)

All these functions are also available from the Main Frame toolbar and the menu Operation.

Do you have a Model View window open? This is the one where you can see the model graphically. If not, open one with Window->New model view from the pull down
menus at the top of the screen. Now, try your luck with the KinematicAnalysis study and the Run button. What should happen is that the model starts to move as the system
runs through 101 time steps of the study.

Since we have no muscles so far, kinematic analysis is really all that makes sense. A kinematic analysis is pure motion. The model moves, and you can subsequently
investigate positions, velocities, and accelerations. But no force, power, energy or other such things are computed. These properties are computed by the
InverseDynamicAnalysis, which is actually a superset of the KinematicAnalysis.

Try the Reset button, and then the Step button. This should allow you to single-step trough the time steps of the analysis. When you get tired of that, hit the Run button, and
the system completes the remaining time steps.

The analysis has 101 time steps corresponding to a division of the total analysis time into 100 equal pieces. The total time span simulated in the analysis is 1 sec. These are
default values because we did not specify them when we defined the ArmModelStudy in the AnyScript model. If you want more or less time steps or a longer or shorter
analysis interval, all you have to do is to set the corresponding property in the ArmModelStudy definition. When you click "Run", all the time steps are executed in
sequence, and the mechanism animates in the graphics window.

So far, the model is merely a two-bar mechanism moving at constant joint angular velocities. There is not much biomechanics yet.
However, the system has actually computed information that might be interesting to investigate. All the analysis results are available in
the ArmModelStudy branch of the tree view. You can expand the tree as shown in the figure to the right.

Directly under the ArmModelStudy branch you find the Output branch where all computed results are stored. Notice that the Output
branch contains the folders we defined in the AnyScript model: GlobalRef, Segs, and so on. In the Segs folder you find ForeArm, and in
that a branch for each of the nodes we defined on the arm. Try expanding the branch for the HandNode. It contains the field 'r' which is
the position vector of the node. We might want to know the precise position of the HandNode at each time in the analysis, for instance if
we were doing an ergonomic study and wanted to know if the hand had collided with anything on its way.

If you double-click the 'r' node, the position vector of the hand node for each time step is dumped in the message window at the bottom of
the screen. So you get the information you wanted, but perhaps not in a very attractive way. But we can do much better than that.
AnyBody has special windows for investigating results. You open them from the pull-down menus by choosing Window -> ChartFX 2D
(new).

This gives you a new window structured just like the editor window with a tree view to the left, but with an empty graphics field instead
of the large text editor field to the right. The graphics field is for graphing results.

The tree in this window is much like the tree in the editor window except that some of the data have been filtered out, so that you mainly
see the parts of the tree that are relevant in terms of results or output. You can expand of the tree in the chart window through ArmStudy
and Output until you come to the HandNode. When you pick the property 'r', you get three curves corresponding to the development of

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 21 of 229

the three Cartesian coordinates of this node during the analysis. Try holding the mouse pointer over one of the curves for a moment. A
small label with the global name of the data of the curve appears. All data computed in AnyBody can be visualized this way.

So far, we have only the kinematic data to look at. Before we can start the real biomechanics, we must add some muscles to the model.

This is the subject of Lesson 5: Definition of muscles and external forces .

Lesson 5: Definition of muscles and external forces


Here's an AnyScript file to start on if you have not completed the previous lesson:
demo.lesson5.any .

We have seen that models in AnyBody can move even though they do not have any muscles. This is because we can ask the system to perform a simple kinematic analysis
that does not consider forces. However, things don't get really interesting until we add muscles to the model.

Skeletal muscles are very complicated mechanical actuators. They produce movement by pulling on our bones in complicated patterns determined by our central nervous
system. One of the main features of AnyBody is that the system is able to predict realistic activation patterns for the muscles based on the movement and external load.

The behavior of real muscles depends on their operating conditions, tissue composition, oxygen supply, and many other properties, and scientists are still debating exactly
how they work and what properties are important for their function. In AnyBody you can use several different models for the muscles' behavior, and some of them are quite
sophisticated. Introducing all the features of muscle modeling is a subject fully worthy of its own tutorial . Here, we shall just define one very simple muscle model and use
it indiscriminately for all the muscles of the arm we are building.

As always, we start by creating a folder for the muscles:

AnyFolder Muscles = {
}; // Muscles folder

The next step is to create a muscle model that we can use for definition of the properties of all the muscles.

AnyFolder Muscles = {
// Simple muscle model with constant strength = 300 Newton
AnyMuscleModel MusMdl = {
F0 = 300;
};
}; // Muscles folder

Now we can start adding muscles. If you want the model to move, you basically need muscles to actuate each joint in the system. Remember that muscles cannot push, so
to allow a joint to move in both directions you have to define one muscle on each side of the joint in two dimensions. If you work in three dimensions and you have, say, a
spherical joint, then you may need much more muscles than that. In fact, it can sometimes be difficult to figure out exactly how many muscles are required to drive a
complex body model. It is very likely that your career in body modeling will involve quite a few frustrations caused by models refusing to compute due insufficient
muscles.

Let's add just one muscle to start with. These lines will do the trick:

AnyFolder Muscles = {
// Simple muscle model with constant strength = 300 Newton
AnyMuscleModel MusMdl = {
F0 = 300;
};
//---------------------------------
AnyViaPointMuscle Brachialis = {
AnyMuscleModel &MusMdl = ..Muscles.MusMdl;
AnyRefNode &Org = ..Segs.UpperArm.Brachialis;
AnyRefNode &Ins = ..Segs.ForeArm.Brachialis;
AnyDrawMuscle DrwMus = {};
};
}; // Muscles folder

This is a definition of the elbow flexor, brachialis. The type of this muscle is AnyViaPointMuscle. It means that it goes from its origin to insertion via a number of
predefined points. The via-points are the AnyRefNodes defined in the second and third property lines. If you have a muscle that goes in a straight line from origin to
insertion, then you can just define two points like we have done here. If you have a more complicated muscle path, then all you need to do is to add the points in between
the origin and insertion.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 22 of 229

The physiological behavior of the muscle is defined by the first property

AnyMuscleModel &MusMdl = ..Muscles.MusMdl;

You can see that it points right back to the muscle model we started out by creating. Notice the two leading dots. Finally, the line

AnyDrawMuscle DrwMus = {};

ensures that the muscle is visible in the graphics window. Lets have a look at it. If you have the Model View window (you know, the one with the rendering of the model in
it) open, then just hit F7. If you don't have the Model View window open, choose Window -> Model View (new) from the pull down menus at the top of the main frame.
You should see a thick, red line connecting the muscle's origin and insertion points. There are other ways to visualize muscles, but we shall save that for the dedicated the
muscle tutorial .

Notice that the muscle's position on the body might be a little strange because we have not yet positioned the segments relative to each other by a kinematic analysis.

All the other muscles are defined in the same way:

//---------------------------------
AnyViaPointMuscle Brachialis = {
AnyMuscleModel &MusMdl = ..Muscles.MusMdl;
AnyRefNode &Org = ..Segs.UpperArm.Brachialis;
AnyRefNode &Ins = ..Segs.ForeArm.Brachialis;
AnyDrawMuscle DrwMus = {};
};
//---------------------------------
AnyViaPointMuscle DeltodeusA = {
AnyMuscleModel &MusMdl = ..Muscles.MusMdl;
AnyRefNode &Org = ..GlobalRef.DeltodeusA;
AnyRefNode &Ins = ..Segs.UpperArm.DeltodeusA;
AnyDrawMuscle DrwMus = {};
};
//---------------------------------
AnyViaPointMuscle DeltodeusB = {
AnyMuscleModel &MusMdl = ..Muscles.MusMdl;
AnyRefNode &Org = ..GlobalRef.DeltodeusB;
AnyRefNode &Ins = ..Segs.UpperArm.DeltodeusB;
AnyDrawMuscle DrwMus = {};
};
//---------------------------------
AnyViaPointMuscle Brachioradialis = {
AnyMuscleModel &MusMdl = ..Muscles.MusMdl;
AnyRefNode &Org = ..Segs.UpperArm.Brachioradialis;
AnyRefNode &Ins = ..Segs.ForeArm.Brachioradialis;
AnyDrawMuscle DrwMus = {};
};
//---------------------------------
AnyViaPointMuscle BicepsShort = {
AnyMuscleModel &MusMdl = ..Muscles.MusMdl;
AnyRefNode &Org = ..Segs.UpperArm.BicepsShort;
AnyRefNode &Ins = ..Segs.ForeArm.Biceps;
AnyDrawMuscle DrwMus = {};
};
//---------------------------------
AnyViaPointMuscle TricepsShort = {
AnyMuscleModel &MusMdl = ..Muscles.MusMdl;
AnyRefNode &Org = ..Segs.UpperArm.TricepsShort;
AnyRefNode &Ins = ..Segs.ForeArm.Triceps;
AnyDrawMuscle DrwMus = {};
};
//---------------------------------
AnyViaPointMuscle BicepsLong = {
AnyMuscleModel &MusMdl = ..Muscles.MusMdl;
AnyRefNode &Org = ..GlobalRef.BicepsLong;
AnyRefNode &Ins = ..Segs.ForeArm.Biceps;
AnyDrawMuscle DrwMus = {};
};
//---------------------------------
AnyViaPointMuscle TricepsLong = {
AnyMuscleModel &MusMdl = ..Muscles.MusMdl;
AnyRefNode &Org = ..GlobalRef.TricepsLong;
AnyRefNode &Ins = ..Segs.ForeArm.Triceps;
AnyDrawMuscle DrwMus = {};
};

Try adding the data and viewing the result by reloading. You should get a picture more or less as what you see below:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 23 of 229

The model does not seem to be correctly connected at the elbow. The ArmStudy actually contains a default operation for getting the elements ordered with respect to each
other. It is the SetInitialConditions study in the tree at the upper left corner of the Main Frame. Try clicking it, then hit the Run button, and the segments fall into position
as shown below.

We now have enough muscles in the model to start computing the muscle forces that can drive the motion. But there is one more detail to take care of, and it is both
important and slightly intricate. The bottom line is: There must be something for the muscles to drive - some load to carry. We have not added any exterior forces to the
model yet, but that is not the problem. You remember, perhaps, from Lesson 2 that each segment has a mass. Additionally, the ArmModelStudy is equipped with a standard
gravity of -9.81 units in the global y direction. This means that gravity actually provides the external force the analysis needs to make any sense.

What is the problem then? Well, unless you specify otherwise, drivers, like the ones we added to the elbow and shoulder joints, act like motors. This means that they
provide whatever moment or force that might be necessary to make the motion happen. Although it would be practical, few of us have motors built into our joints. Instead,
we have very efficient muscles so we want to leave the task of providing force in the model to them. The way to do that is to set a property called Reaction.Type for the
driver to zero. This is how it's done for the shoulder:

AnyKinEqSimpleDriver ShoulderMotion = {
AnyRevoluteJoint &Jnt = ..Jnts.Shoulder;
DriverPos = {-100*pi/180};
DriverVel = {30*pi/180};
Reaction.Type = {Off};
}; // Shoulder driver

This additional line makes sure that the driver provides the motion but not the moment. Why is AnyScript made that way? Why would anyone ever want to model a joint
with a motor in it? The explanation is that AnyScript models for ergonomic studies often comprise machinery that the body of the model is connected to. And this
machinery can have motors that provide moment or force input to the system. Why is the motor then switched on by default? Well, models under development often do not
have enough muscles to move. Such models will not work before the last muscle is added unless they have motors in the drivers, and it is practical to be able to run an
analysis now and then during development to check that the model works correctly.

As you can see, the single Off is encapsulated in braces, {Off}. This is because it is a vector. A driver by default has several components and hence all the data in the driver
is vector quantities. For semantic reasons this applies even when the driver only controls one degree of freedom as it does here.

Add a similar line to the definition of the elbow driver and we are ready to compute muscle forces. Click the InverseDynamicAnalysis in the study tree at the bottom left of
the screen and then the Run button, and watch the model move. It should look exactly like in the kinematic analysis, however, during this analysis, the AnyBody system
computes all muscle and joint forces in addition to a whole lot of other useful information. To see it, you once again have to open a ChartFX window (if you don't have the
one we used previously open) by means of the menu Window -> ChartFX 2D (new) in the pull down menus in the top of the main frame. In this new window, expand the
ArmStudy -> Output -> Model -> Muscles branch. You should see a list of all the muscles appearing. Each of them can be expanded to reveal the data inside. Let us
expand the brachialis muscle and investigate its force variation over the movement. You should see a node named Fm. If you click it, you should get a curve like the one
shown below:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 24 of 229

Notice that the force in the muscle drops as the movement proceeds. This is quite as expected, because the moment arm of the gravity about the elbow gets smaller as the
elbow flexes, and less muscle force is therefore needed to carry it. If you look at the muscle force in the BicepsLong, you see a different pattern:

This muscle grows in force during the movement. That is because it is influenced by the movement of two joints, namely the shoulder and the elbow. In addition, it
collaborates both with DeltoidusA on shoulder flexion, and with the other elbow flexors, and these muscles all have to level their work in relation to each other.

This might sound like there are heuristic rules built into AnyBody. This is not the case. AnyBody distributes the work between the muscles in a very systematic way: It
solves an optimization problem to actuate muscles so that the maximum relative load on any muscle is minimized. This corresponds to postponing muscle fatigue as far as
possible, and it causes muscle to collaborate as much as they can. This sometimes involves development of antagonistic muscle forces, i.e., forces that appear to contradict
the movement but in fact relieve weaker muscles of load. Muscle synergy and the occasional presence of antagonists is well known from many experiments, and the
minimum fatigue criterion used in AnyBody reproduces this behavior.

Now that we have the analysis going, we might want to investigate the model's behavior in different situations. A typical example could be to see how it carries an external
load in addition to gravity. Let us imagine that the model is performing a dumbbell curl where it carries some load at the hand. We start by attaching a node to the forearm
at the position of the palm. Add this definition to the ForeArm section:

AnyRefNode PalmNode = {
sRel = {0.27,0,0};
};

The next step is to add an external force. We make a folder for this purpose:

AnyFolder Loads = {
//---------------------------------
AnyForce3D Dumbbell = {
AnyRefNode &PalmNode = ..Segs.ForeArm.PalmNode;
F = {0,-100,0}; // Force in Newton
};
}; // Loads folder

That's all there is to it. Now you can analyze how the model will react to a downward force of 100 N (approximately 10 kg dumbbell weight). If you reload, rerun, and
investigate the BicepsLong force again, you should see this:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 25 of 229

The muscle force is obviously much larger than before, and the development is also different. It now reaches a maximum during the movement and drops off again.

Applied forces do not have to be constant. They can change with time and other properties in the model. Please refer to the tutorial on forces for more details.

There are infinitely many studies that could be made using even a simple model like this one, and you are encouraged to experiment a little or a lot. To get reliable results,
however, would take at the very least an individual definition of the muscles with a realistic strength for each of them, and a more detailed modeling of the deltoid's origin-
insertion path in the shoulder; it can be a comprehensive job to define a realistic body model which is exactly why most users would probably start out using the body
model available in the AnyBody Managed Model Repository .

This tutorial, being of introductory nature, will instead skip to a new subject: How can we add realistic geometries of bones and other elements to our model?

Now, let's continue to Lesson 6: Adding real bone geometrics

Lesson 6: Adding real bone geometries


Here's an AnyScript file to start on if you have not completed the previous lesson:
demo.lesson6.any .

So far, the graphics of the model you have developed is what we can call a stick figure representation. This is a straightforward way of seeing the model and it reflects the
mechanics very vividly, but it does not look very physiological. You may be wondering how you can add cool bones and other geometries that will impress your colleagues
and look good in your presentations. You may want to put your model into an environment such as a room, a treadmill, or a bicycle to illustrate the purpose of the model.

However, there may be other reasons than mere aesthetics why it can be advantageous to work with real geometries. When attaching muscles, for instance, a real bone
geometry gives you an instant visual feedback on where the muscle is located in the organism as illustrated by the two pictures above.

Adding geometric models such as bones is fortunately very simple. All you need is a file with a 3-D graphical representation of the bone or other component you may wish
to add. The format of the file must be STL ascii. STL is a very simple graphical file format that basically contains triangles. Virtually any CAD system you can think of can
save geometry on STL format, so if you have your geometry described on IGES, STEP, DXF or any other usual type, just run it through your favorite CAD system and
convert it to STL. STL comes in two varieties: ascii and binary. AnyBody needs an ascii file, so please make sure to choose that option if you create your own STL files in
a CAD system.

The bone models you see on the pictures above are a bit elaborate for a short tutorial, so we shall start with something a little simpler. What we want to do now is to add a
dumbbell geometry to the arm model we have just created. You can find a file to use here . Right-click the link, choose "save as", and put the file in the directory where
you have placed the arm model.

The dumbbell should be added to the forearm, so the first thing to do it to add a reference to the STL file we just saved to the definition of the forearm:

AnyDrawSeg DrwSeg = {};


AnyDrawSTL DrwSTL = {
FileName = "dumbbell.stl";
};
}; // ForeArm

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 26 of 229

Try reloading the model again. You will probably see nothing but grey the Model view. A closer investigation of the problem would reveal that the entire arm model is
actually situated inside the dumbbell handle. This is because the STL file was created in millimeters, where the arm model is in meters. Rather than going back to whatever
CAD system was used and scale the dumbbell model down 1000 times, we can add the scale definition to AnyScript in the following way:

AnyDrawSTL DrwSTL = {
FileName = "dumbbell.stl";
ScaleXYZ = {0.001, 0.001, 0.001};
};

When you reload the model, the picture you get should be similar to what you see below. The dumbbell is visible now and has the right size, but it is sitting at the center of
gravity of the lower arm rather than at the hand, and it is not oriented correctly.

The fact is that, when you attach something to a segment, it is positioned at the segment's origin which is usually the same as the center of mass. However, you can also
attach stuff to points, so moving the dumbbell to the hand is simply a question of moving the reference to it from the ForeArm segment to the PalmNode that we defined
previously. Block the entire AnyDrawSTL folder with the mouse and cut it out. Then re-insert it under the PalmNode like this:

AnyRefNode PalmNode = {
sRel = {0.27,0,0};
AnyDrawSTL DrwSTL = {
FileName = "dumbbell.stl";
ScaleXYZ = {0.001, 0.001, 0.001};
};
};
AnyDrawSeg DrwSeg = {};
}; // ForeArm

On reload, this produces a new picture with the dumbbell attached at the right location, but it is still not oriented correctly.

We want to rotate the dumbbell 90 degrees about the y axis. We could do that by going back to the CAD system and modifying the dumbbell STL file, but an easier option
is to rotate it directly inside AnyScript.

A geometrical object that you insert gets the same orientation as the coordinate system it is attached to. In this case the dumbbell is attached to PalmNode. Nodes are
actually reference frames with the ability to be positioned and oriented relatively to other reference frames, for instance a segment or another node. We have already
positioned nodes by means of the member vector sRel and relative orientation happens similarly with the member matrix ARel, the relative rotational transformation
matrix. We wish to rotate the dumbbell 90 degrees about the local y axis and hence write:

AnyRefNode PalmNode = {
sRel = {0.27,0,0};
ARel = RotMat(90*pi/180, y);
AnyDrawSTL DrwSTL = {
FileName = "dumbbell.stl";
ScaleXYZ = {0.001, 0.001, 0.001};
};
};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 27 of 229

As a final cosmetic touch, you may want to change the color of the dumbbell. This can be done by adding the property RGB to the STL file reference:

AnyDrawSTL DrwSTL = {
FileName = "dumbbell.stl";
ScaleXYZ = {0.001, 0.001, 0.001};
RGB = {0.2,0.4,0.5};
};

The RGB property specifies the blend of colors Red, Green, and Blue in that order for displaying the STL geometry. The combination above produces a dull blue shade.

This completes the Getting Started with AnyScript tutorial. The final result of the efforts is in demo.arm2d.any .

Interface features
This tutorial deals with the interface features of the AnyBody Modeling System. Before trying your luck with this tutorial, please complete the Getting Started with
AnyScript tutorial .

Much of the interface works like other types of windows software; you can copy and paste data, and you can arrange the various windows as you would expect. But
AnyBody does computations that no other computer system is capable of, and this calls for some special features.

We need something to work on. Please download this file , save it in a working directory of your choice, and load it into the AnyBody Modeling System.

The squat problem

The file you have loaded is a squat example. It is a 2-D model and contains only a single leg with eight muscles. The strength and mass of
the single leg correspond roughly to two ordinary legs.

The arm of the model is used for balance. It does not have any muscles, and it has no explicit driver attached, but if you run the kinematic
analysis or the inverse dynamic analysis on the model you will see that the arm moves to maintain the balance of the model. This is because
the model has a driver on the position of the collective center of mass requiring it to be directly above the contact point with the ground,
which the model accommodates by movement of the arm.

This tutorial consists of the following lessons:

 Lesson 1: Windows and workspaces


 Lesson 2: Editor Window Facilities
 Lesson 3: The Model View Window
 Lesson 4: The Chart View
 Lesson 5: The Command Line Application
 Lesson 6: Browsing the Model via Model Tree and Object Description
 Lesson 7: Modifying the Loaded Model
 Lesson 8: Wrapping the Model with AnyBody Project

Let us quickly proceed to the first lesson: Windows and workspaces .

Lesson 1: Windows and workspaces


When you work with a model like this, you are likely to initially go through a series of model refinements, subsequently conduct a number of investigations, and finally
extract data for further processing or reporting. This may be a process going on over a longer period where you start and stop the AnyBody Modeling System several times,
and you want to quickly come back to the windows layout fitting the task at hand. This section is about how to control your windows layout.

When you start the AnyBody Modeling System, load the model, and open a model view window, you will get the standard layout of windows in the AnyBody workspace.
It looks like this:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 28 of 229

This layout is standard because it gives you a little bit of everything. But it may not be what you want for a particular task. You may also find yoursef doing a number of
basically different tasks for which different windows layouts are convenient and being annoyed about having to change layout every time you change task. Therefore, the
system offers you three different user layouts that you can set up as you like and switch between. If you look at the top of the main window, you will notice that the button,
L1, is pressed in.

This indicates that you are now working in the first of the three user-defined layouts. Each layout can contain a different user-defined window setup, and you can switch
between them by a single mouse click. Try running the HeelUpStudy.InverseDynamicAnalysis and open a ChartFX window to investigate the results. Perhaps you want to
simultaneously see the Model View window, the Chart window and the AnyScript code, while you are not particularly interested in the Operations window at the bottom of
the screen. You might arrange the windows as show below.

Suppose you have very carefully set this window layout up and want to keep it for later use after you have worked with another layout. How can that be done? Simple, you
just press the L2 button. This will give you a fresh layout to work on, and you can always go back to what you had by pressing L1 again. Whichever layout you create
under one of the L1, L2, and L3 buttons is kept for later use.

Workspaces

So, how do you preserve all the windows layouts when you have invested much time in setting them up and have to shut your computer down for the night? The answer is
to save the workspace. A workspace file is a description of the state of your user interface. Notice the title of the main window:

It says "New Workspace" because you did not load a workspace when you started, and you have not yet saved the one you have created. Click File-> Save Workspace as...,
pick a directory and a suitable name, and save the workspace. Then exit AnyBody, and start the system again.

When you have re-started, click File->Load Workspace..., browse your way to the workspace file you just saved, and load it. You will get the windows layout back that
you had when you started. You can also find a workspace file in Windows Explorer and double-click it. The workspace files have the extension .anyws.

In addition, you can convenniently find recent workspaces in the AnyBody Assistant dialog box, please see the picture below. In the Recent Project files tab, you will find
recent workspaces and main files listed. A complete list of recently uses AnyScript files is found in the Recent *.any files tab.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 29 of 229

Window properties

Each window is equipped with a number of properties that are saved with the workspace. This set of properties is often updated in newer version of AnyBody in order to
make the workspace storage of your working environment as good as possible and in order to match new functionality added to the windows.

Some of these properties can be accessed and set by the user. This can be done from the Main Frame menu item Windows -> GUI Properties. Selecting this item opens a
the Properties Window that show the properties of the current window. Some windows, where frequent access to the properties may be needed, for instance the Model

View and AnyChart View, have a button on thier toolbar for easy access to the properties. Look for a button looking like this on the toolbar of a window.

In the next lesson we shall proceed to have a closer look at the individual window types, and why not start with the Editor Windows .

Lesson 2: The Editor Window


We need something to work on. Let us create a blank file and type something into it using the editor. The way to do that is to click the "New Include" button on the toolbar:

This brings up a new editor window with an empty file, and we can go ahead typing anything we want. The first thing you have probably noticed about the AnyScript
editor is that it recognizes the predefined class names and highlights them automatically. It does this all the time as you are typing, and it is a great help to avoid
misspellings that might later lead to annoying syntax errors.

Syntax Highlighting

When you start typing something, the writing color is black. This is the standard color in the editor for things that have not been recognized. For instance, if you start
defining a segment, you may type (try it!):

AnySe

And the text remains black until you type the last character of the reserved word:

AnySeg

at which point the text becomes blue. This can be a great help if you are not quite sure about the name of a particular object. You can try typing the different forms of the
name, and when you hit the right one, the text turns blue. The editor similarly recognizes comments. If you precede the AnySeg class name with a double-slash, the entire
line turns green:

// AnySeg

Please notice that similar to C, C++, Java, and JavaScript you can turn entire blocks of code into a comment by encapsulating it into a pair of /* */ delimiters. Another easy
way to temporarily remove and re-activate several lines from the file is to block the text in question and use the two buttons in the toolbar of the Editor window.
This automatically places or removes double slashes in front of each line in the block.

Please also notice the so-called Documentation Comments. This is comments using the following syntactical forms: /// ..., /** ... */, ///< ..., and /**< ... */. The
Documentation Comments are related to a given object in the model and these comments are treated specially so the information can be accesses more convenniently after
loading the model and thereby help the user of a model to understand the model without reading the code. In the editor, the Documentation Comments do however have the
same color as other the normal comments. The Documentation Comments' form is similar to other source code systems like JavaDoc, Doxygen, and others.

Automatic Indentation

When developing software that is hierarchical it is customary to indent the code according to the hierarchical level of each line. This greatly improves the legibility. In the
AnyScript editor we have decided that the standard indentation for each level is two spaces. The editor automatically keeps track of where you are in the code as defined by
the start and end braces, and it helps you make the right indentations as you type. Let us continue the segment definition we started above. Remove any leading double
slashes and proceed to type

AnySeg Segment1 = {

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 30 of 229

and hit the Return key to change line. Notice that the editor automatically indents the next line by two spaces. This is because it has noticed that you have stepped on level
down in the hierarchy relative to the first line by the start brace. Every subsequent line you type will begin two spaces to the right of AnySeg. You are not forced to accept
this. You can easily backspace to the beginning of the line and start your typing there, if you like that better. You might write something like:

AnySeg Segment1 = {
Mass = 1.0;

The editor will discover that you did not like its suggested indentation, so the next line you type will begin at the same character as Mass, and you may proceed to finish the
definition of the segment by typing:

AnySeg Segment1 = {
Mass = 1.0;
Jii = {0.1,0.01,0.1};
};

Auto format

Perhaps you decide at this point that the indentation is better after all. (If you do not decide at this point, you surely will when you have written a few hundred lines and are
trying to balance your start and end braces.) So, how can you restore the default indentation? Well, the AnyScript editor has a very nice feature called Auto format. It
allows you to block a part of the code or the entire file and indent it in one simple step.

Try highlighting the block you have written , and press Alt-F8. You should get this result:

AnySeg Segment1 = {
Mass = 1.0;
Jii = {0.1,0.01,0.1};
};

This facility is also available in through the pull-down menu Edit->Format Indentation.

If you are ever in a situation where the model will not load and you suspect that you have forgotten a brace somewhere, simply block the entire file and apply Auto format
to it. You will usually be able to see by a few glances where the error is located.

You can also manually control the indentation of a block of lines. A highlighted block of text can be indented or unindented in steps of two spaces by pressing Tab or Shift-
Tab.

Tree Views

The structure of an AnyScript model is hierarchical. This means that it is obvious to represent the loaded model as a tree, and the system makes extensive use of this
representation in all its different window types. If you still have the squat model from the previous lesson open, go to the main file and load it (key F7). You should see a
tree at the left hand side of the editor window as in the figure below.

What you see here is the Model Tree, which it the main tree view of AnyBody showing all objects in the loaded model in the structure they are created in the AnyScript
code. The Model Tree is in principle available in many of AnyBody's windows, but some of the information is filtered out in some window types to make the tree view
practical for specific purposes such as browsing output or operations in the model.

The Editor windows have the complete unfiltered Model Tree, and they can take up a significant space in the Editor window. Therefore, they are by default collapsed to
maximize the space for editing and an unfiltered Model Tree is also available on the Main Frame, which is sufficient for most purposes. Multiple Model Trees can,
however, be handy when working with large models and browsing for information in different places of the structure; this is the reasons for having the option of opening a
Model Tree in the Editor windows. Moreover, the Model Trees in the Editor have to options for interaction with the code of the particular Editor Window, which is not
available from the Main Frame Model Tree. You can collapse the tree again after opening it by clicking the X tab on the left hand side of the tree.

We shall not go into details about the functionality in the Model Tree, but notice that right-clicking an object in the Model Tree give you access to these functions. There
are two categories of these functions:

1. Interaction with the AnyScript code such as inserting object name into the code at the place of the cursor
2. Class Operations that are operations associated with the AnyScript classes. These cannot be explained in detail here because the follow the classes, but there are a
couple of very basic Class Operation that is available to all objects.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 31 of 229

In particular notice the Class Operation called Object Description that comprise much practical information for the given object, including the Documentation Comments
made by the AnyScript programmer making the model. The Object Description is very useful when browsing the model because it contains active links, which for instance
can bring you to the code with single click. The Object Description is considered to be the most fundamental operation in the Model Tree so it will be activated when you
double-click any node in the tree.

The Model Tree offers you several options to go from the tree to associated places the AnyScript code. There are, however, also options to go the opposite way, i.e. from
the code to the Model Tree. Try right-clicking the code. You will them get a pop-up menu with several editor options. One of these is "Locate in Model Tree". It will
probably be greyed, i.e. disabled, because you have not selected anything that can be related to the tree. But if you try highlighting an object name in the code it should
become active. Selecting this will bring you to the specific object in the Model Tree. In some cases, there is not a single clear one-to-one correspondance between the code
location and the Model Tree. This happens if the code, you look at, is in an include file that have been included several times in the model. In such cases, the Editor will
provide you with a list of options to select from.

As you can see, there are also other tree views available. Clicking the Files tab will give you an overview of the model's include file structure. Models in AnyScript are
often divided over several files where one main file links to other files, which link on to other files and so on. The links are realized by means of include statements in the
AnyScript code:

#include "includefile.any"

The File Tree is very unimpressive in this model because it does not have any include files, but below you see a File Tree from a more complicated model:

The leaves in the tree are marked by two different icons. The icon with the little red # sign points to a place in the model with an include statement. If you double-click
such a line you will be taken to the position of the include statement. If you Click the + to the left of the icon, the branch folds out, and you see another icon below without
the # sign. If you click this icon, the include file itself opens up in an editor window.

The third tab in the tree view is named Classes. It gives you access to a tree of the predefined classes in the system. From this tree you can insert templates of new objects.
This eliminates much of the need to remember the syntax of each object and saves you many lookups in the reference manual. The use of the Classes Tree is described in
the Getting Started with AnyScript tutorial .

There are a couple of more tree views. These contains global objects that are available to your code. Global AnyScript constants are listed in one tree and global AnyScript
function in another.

Find and Replace

No editor is complete without a find and replace function. The function in the AnyScript editor is not much different from what you find elsewhere. It is accessible through
the Edit menu or by the keyboard shortcuts

Ctrl-F for find


Ctrl-H for find and replace.

F3 repeats the previous find operation.

Support for External Editors

Some users have very strong preferences when it comes to editors. The AnyBody Modeling System allows you to use any text editor you like to author your models as long
as it saves the files on an ascii text format.

The Main file must be open in the AnyBody Modeling system initially to allow compilation. Once you have compiled it, the system remembers the current Main file, and it
will re-compile it every time you press F7. This means that you can edit and save any Main or include file by means of an external editor and compile it from inside the
AnyBody Modeling System.

So what happens if you have a file open in an AnyBody Editor Window, and you are simultaneously editing it in an external editor? Well, every time you press F7 to
compile the model, the system will attempt to save any changed files to pass them on to the compiler from the disk during the compilation. But before the system saves the
file, it checks if the file has been updated from elsewhere, for instance from an external editor, and the system will ask you if it is supposed to load the newer file into the

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 32 of 229

AnyBody Editor Window.

 If you answer yes, the new file is loaded and used in the compilation.
 If you answer no, the old file is saved and used in the compilation, overwriting whatever you have saved from the external editor.

Let us venture to have a closer look at the Model View

Lesson 3: The Model View Window


The Model View window is the system's graphical representation of the model. You can open a Model View window by the Window->Model View (new) command.

The Model View displays a special type of model elements that we usually call "Draw Objects". These are the objects you can attach to the segments, muscles, nodes,
surfaces and such on the model. Most classes in AnyScript that are related to mechanics in any way have corresponding draw classes, and the library of draw classes is
constantly being extended and improved.

In older versions of AnyBody, draw objects were the only objects being displayed in Model View; there was a complete separation between mechanical objects being used
in the simulations and draw objects being shown in Model View. However, this has changed in newer versions (from about version 4.1.x) where many objects were
equipped with so-called auto-generated draw objects (or default draw objects). These draw objects are virtual, i.e., they do not appear in the Model Tree, but they are (or
can be) visible in Model View. Therefore auto-generated draw objects cannot be modified to the same extent as model-defined draw objects, because there are no
accessible settings. It should be noticed that many models, even in the AMMR repository is still using model-defined draw objects extensively, for no other than historic
reason, but model-defined draw objects are still useful for taking control on what appears in the view.

This lesson looks into the functionality of the Model View, and even though you can probably use it intuitively, you may also pick up a useful trick or two you did not
know about. The lesson is divided into the following two sections:

· Introduction to the Model View

· Working with the Model View contents

In the former, we shall look at the Model View window itself and its functions and in the latter we shall look briefly at the options for modifying the contents of Model
View.

Introduction to Model View


When active, the Model View updates the model as the computation proceeds. The update can involve the elements moving on the screen or colors or shapes changing to
reflect the state of the model such as, for instance, muscle forces.

If the model is not too big and the computer is not too slow, the computation runs fast enough to create a dynamic animation in real time or close to that. However, for
many larger models, the computation is too slow to give you a dynamic impression of the model's movement. The model view then provides the opportunity to save the
individual frames for subsequent processing into a video animation that you can play at any speed you like. Many study classes, such as all mechanical studies, is also
equipped with a Replay operation. This operation plays back the data from the output data structure, where it was stored during the simulation, to the real objects of the
model and Model View will then display the given state of the model again. This is significantly faster than the simulation for large models.

As usual, we need a model to work on. For this tutorial you can pick any model you may have, or you can download the familiar dumbbell example here:
demo.arm2d.any . You will also need the accompanying STL file: dumbbell.stl .

Load the model into the AnyBody Modeling System and click Window -> Model View (new). You should get a window looking like this:

 The model is centered in the window, and you should be able to see all its elements. When you open a new Model View, the window automatically applies a Zoom
All function that shrinks the view until all elements are visible.
 The model is not necessarily assembled correctly. All the segments at load time are positioned where they are defined in the AnyScript model. These positions rarely
comply with the kinematical constraints such as joints. In fact, you might want to assemble the model above correctly by selecting and running the

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 33 of 229

SetInitialConditions operation in the ArmStudy at the lower left corner of the screen.

This resolves the kinematical constraints and puts the model into the position defined by its drivers at time step 0. It produces the picture shown below.

Notice that we are looking at the model directly from the side. The default viewing direction is the xy plane. This coincides well with the International Society of
Biomechanics standard of letting the saggital plane coincide with the global xy plane.

The Toolbar

The Model View has its own toolbar with following button functions:

 On/Off: This button switches automatic update of the window on and off. When switched off, the window does not update when the model is moving, and it is not

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 34 of 229

possible to rotate, scale and pan the view. The advantage of switching the update off is that it makes the analysis run faster, especially on computers without a
separate graphics processor.

 Properties : Button that opens the properties window (equivalent to menu item Windows -> GUI Properties). In the properties, you have options for setting
properties more specifically. We shall not go into details about these options here, see below.
 Pan tool: Selecting this tool causes the cursor to change shape to a hand. When you drag the mouse over the screen with the left button down, the picture moves with
it.
 Zoom tool: When this tool is active, the cursor resembles a small magnifying glass. When you drag the mouse over the picture with the left button down, it zooms in
or out for upward or downward movements respectively.
 Spin tool: This tool allows you to spin the model dynamically on the screen by dragging the mouse with the left button down. The function is very intuitive and you
will soon get the hang of it. It works like the model is attached to an imaginative sphere centered on the screen. When you hold down the left mouse button, you are
grabbing the surface of the sphere and spinning it with the movement of the mouse.
 Default views: These three buttons represent predefined viewing directions: the xy plane (standard), the yz plane, and the xz plane respectively.
 Zoom all: This button refits the view to contain all the drawing elements.
 Record: This button starts video frame capturing explained in more detail below.
 Frame count: This panel displaying the number of captured frames during a recording.
 Stop recording: This button stops a video frame capturing session. The function is explained in detail below.

Model View Properties

The Model View properties accessible to the user contain three groups:

1. View point settings that are also set by the typical interaction with Model View through Pan, Zoom and Spin operations. These settings in the Properties can be set
directly or they can be grabbed for use in a camera implemented into your model. The view point definition in the properties of Model View is using the AnyScript
class AnyCameraModelView. This is done to enable easy exchange of view point properties between model and Model View. The individual properties are
introduced in the AnyScript Reference Manual.
2. Viewer properties that control viewer behavior.
3. Scene properties that control general scene properties, such as background color, that are not given in the model definition.

Recording video

You may want to save a video file of your simulation for a presentation or simply to be able to show a large model running in real time. The model view provides the
opportunity to save the individual graphics frames for subsequent processing into a video animation that you can play at any speed you like.

The function works much like a video tape recorder in the sense that you can push the red record button any time you like, and what happens in the
window is subsequently saved for further processing. Let's see how it works. Try clicking the record button. A file manager will pop up and request you
to select a location and a naming of the files you make. The name you select will be appended with _nnn where nnn if the frame number of each image.
You can also select the image file type, and jpeg is usually a good choice to limit the size of the images on the disk.

You will notice that the frame counter lights up, the "Rec" letters flashes, the record button becomes inactive indicating that you cannot push it twice, and the stop button
becomes active indicating that you can push it.

Everything that takes place in the window will now be recorded. Try spinning the model around a little with the mouse and notice how the frame counter adds up. Notice
that the system is intelligent enough to not record anything when nothing is happening. This means that you are in no hurry when you have pushed the Record button. The
system only grabs frames when the picture actually changes. This happens either when you manipulate the picture manually as you did here, or when an analysis is running
and producing new pictures as it proceeds. If you record an analysis with 100 time steps, then you will get 100 frames saved.

When you have 50-100 frames, push the "Stop recording" button. The system will ask you whether you really want to save the frames. If you answer no, they will be
erased. If you save the frames you will be left with a bunch of image files like this:

The AnyBody Modeling System does not provide a video editing facility to process these files into an AVI, MPEG or similar video file format. However, many really good
and cheap utilities are available for this purpose. We at AnyBody Technology use a very good and inexpensive tool called VideoMach available from www.Gromada.com .

Size matters

Regardless of how videos are processed, they are rather data intensive, and it is a really good idea to plan the recording well. Depending a little on the image format, the
size of the frames you are saving is proportional to the area of the Model View. This means that it is more rational (and usually gives a better result) to resize the shape of
the Model View to the animation you want in the end, than it is to change the size or crop the video afterwards.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 35 of 229

Working with the Model View contents


We have already mentioned that Model View shows draw objects in the model and that there are two types of this kind of objects

· Auto-generated draw objects

· Model-defined draw objects

Basically, you can say the auto-generated draw objects serve to provide a picture of the model while building and working with it on a fundamental level, whereas model-
defined draw objects serve to make the best possible views that suit your particular purposes of communication.

All draw objects can be appear in the following states:

· Visible or invisible

· Transparent

· Selected

These states you can control while the model is loaded, either directly from Model View or from the Model Tree. We shall return to this in a moment.

By default draw objects may be either visible or invisible. This implies that you will normally not see all draw objects, since it would make the Model View too congested
and messy to be useful. In the system, there is a definition on what to make appear by default. This is still a young feature, so it may change in the coming versions, but
some basic lines are that

· Model-defined objects overrule auto-generated objects (i.e. make then invisible, but they are still there)

· The more important auto-generated draw objects, such as segments, will be visible by default when no model-defined drawing objects are defined for the
corresponding mechanical object, whereas others serve more to provide further details of the model, such as kinematic measures, and are therefore invisible by default.

Model View State Actions


Let us take a look at how you can interact with the Model View states of the draw objects. Right-clicking the Model View will bring up its context menu and from here you
can apply Model View state actions on the objects. If you hit an object during the right-click command, you get the context menu related to this object.

From here you can show, hide, make transparent, etc. Reset means to bring the object back to its original state (loading time), which can be both visible and invisible
depending on the object.

The lower part of the menu shows you part of the Model Tree (as menu items), i.e. the entire tree related to the draw object you have hit. This provides you with the
possibility to interact with an object higher in the Model Tree; for instance you may want to interact with the segment you are looking at, even though you have actually hit
the draw object of the segment. In another situation, you may actually want to interact with the draw object, if you are not studying the mechanics of the model but the
view of it.

You can unfold one deeper level of the context menu for any model item in the lower part of the menu. This action will reveal the same menu for any object:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 36 of 229

From here you can interact with the object in many ways, either the object itself (This object) alone or if it is a folder containing other draw-able objects, with these as well.
Folder contents can be interacted with either 1 folder level down or all levels down the folder tree, or you can do with certain practical class filters such as segments,
muscles, etc. The predefined filtered interaction options always affect all objects of the selected type in the folder tree from the selected starting point and down. No matter
which selection you make at this menu level, you have the same options for invoking Model View state actions to the objects. The image below shows these options in the
final level of the context menu.

If you right-click the background, you will only find Main, i.e. the root folder of the model. On this you have the same options as on other folders in the model tree. This
can be powerful for “cleaning up” your view before making specific setting or for making sure that you see all objects of a certain type, e.g. all segments or all muscles.

Selections in the Model View

Graphical objects in the Model View can be selected by single-clicking them with the left mouse button. Doing so will visually mark the object as selected by turning it
into a reddish-pink color. Multiple objects can be selected by left-clicking the objects sequentially. Left-clicking a selected object again will remove it from the current
selection. The currently selected objects can be deselected by either left-clicking somewhere on the background, or by using the “Deselect all” option in the right-click
context menu.

When right-clicking a selected object, the resulting context menu will give a number of state actions for the selection instead of the normal right-click context menu. These
state actions will apply to the entire Model View selection and not only the right-clicked object.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 37 of 229

Model View State Actions from the Model Tree

The context menu options for setting Model View state action for draw objects is also available from the Model Tree. The context menu in the Model Tree has a Model
View item, which holds exactly the same sub-menu we looked at above, please see the image below.

This provides another intuitive tool manipulating the contents of Model View.

Draw groups

We should now mention a special class for assisting you in applying the state actions you want on the model. It is the “draw group” with class name AnyDrawGroup. A
draw-group object can refer (with object-pointers) to a set of objects in the model. When you perform any of the Model View actions explain above on a draw-group, the
group object will transfer the action to all objects it refers to.

The object-pointers in the draw group can be established in the model using search functions of your choice, so it provides a powerful tool for preparing your model for
special Model View state actions. Please refer to the class AnyDrawGroup for more details and in Lesson 8 , you can find an example of their usage.

The next lesson deals with the two different Chart Views for investigating analysis results.

Lesson 4: The Chart Views


The AnyBody Modeling System has two different window types for graphing results:

The ChartFX View and the AnyChart View. The former gives you a large gallery of different graph types to choose from and has useful features for interfacing with other
windows applications such as the option to copy data on many different formats. However, this view is restricted to two-dimensional graphs.

The AnyChart View gives you the opportunity to make three-dimensional surface plots. It is based on the AnyScript drawing object class also called AnyChart and this

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 38 of 229

reuse of functionality allows you to make identic charts in the AnyChart View and inside the model scene, i.e., in Model View. AnyChart is still a fairly simple chart
option, but its functionlity is being extended in future version of AnyBody.

The ChartFX View

Do you still have the demo.Arm2D.any model loaded? If not, try loading it in and we'll play a little with it and see how results can be investigated.

Please load the model and run the ArmStudy.InverseDynamicAnalysis. Then open a ChartFX View by clicking Window -> ChartFX (new). You will get a window like
this:

Notice that the window like all other windows in the AnyBody Modeling System is divided into a tree pane on the left and the actual data
area to the right. If you play around a bit with the tree you will soon see that it resembles the trees from most of the other window types,
but that some stuff is missing. This is because the tree is filtered, and it requires a further explanation:

The AnyBody Modeling System contains a special type of data called output data. This is essentially what comes out of a computation.
Output data is organized in series with one item for each time step of the analysis, so the output data is not available until an analysis has
been performed. The tree in the Chart View has been filtered such that you only see the output data. This makes browsing a bit less
confusing. However, the tree retains its basic structure, so to get to useful data you normally have to expand the tree through
Main.ArmStudy.Output.Model. Notice that the other option next to Output is Abscissa. The standard Abscissa in an
InverseDynamicAnalysis is time, so if you expand the Abscissa branch and click the 't' variable, you will get a straight line with slope 1
because you are plotting time against time.

Global output data

Directly under output you also find some data pertaining to the "global" properties of the model:

 Ekin - the total kinetic energy of the system


 Epot - the total potential energy of the system
 Emech - the total mechanical energy of the system, i.e. the sum of potential and kinetic energies
 Pmech - the mechanical power of the system

Try clicking Ekin, Epot, and Emech in turn. You will notice that Epot and Emech are very similar. This is because the movement in this model is relatively slow, so the
kinetic energy remains small throughout the simulation and has little influence.

The KinematicError is not very interesting unless something is wrong with the analysis. It stores the error in the kinematic analysis as a measure of how far the kinematic
constraints of the problem are from being satisfied. Normally this should be zero or very close to zero. If is it not, information about the development of the kinematic error
may help you determine the cause of the problem.

Finally, the MaxMuscleActivity is the a measure of the overall effort of the body model but it requires further explanation, so we shall get to it a little later.

Time-dependent data

The predominant way of looking at data is as a function of time or rather time steps. If you expand the Model branch into the Segs section, you can investigate the
movement of the "hand" of the model as shown in the figure above.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 39 of 229

Expand the tree until you get to the HandNode object as shown to the left. Then click the r property. This displays three curves on the screen corresponding to the x, y, and
z coordinates of the handnode as the arm moves. The z coordinate is zero because it is a 2-D problem. By the way, the color codes of the chart view are red, green and blue
in that order, so red is for x, green is for y, and blue is for z.

Let us look as more complex data. Most users of musculoskeletal analysis are interested in muscle forces. In this model we can find the muscles in the tree by expanding
the nodes Main.Model.Muscles. Take the first muscle, brachialis, and click the Fm property.

Fm is the muscle force, and as you can see, the brachialis force declines as the arm moves. Not all of the muscle data items in the tree contain any reasonable results. It
depends a bit on the muscle model in question. But the muscle force, Fm, and the active state, Activity, are always available. Please refer to the Muscle Modeling tutorial
for more information.

Detailed data investigation

Having an item graphed you may want to investigate the results a little closer, and the toolbar above the graph gives you
different options for doing so.

However, the first thing you might notice is that if you hold the mouse pointer still above the curve for a short moment, a
small box will pop up and give you the name of the data series and the value of the closest data point. In the example to the
right you can see how the little box informs you that the curve passes through point (0.04; 1.46e+002). Please notice that the
decimal commas are because this picture is made on a computer with a European language setting. Notice also that the Chart
View uses 'x' and 'y' to designate the two axes regardless of which parameters are actually being graphed.

To facilitate studying of the details of the data you can switch on the grid lines horizontally, vertically, or in both directions
simultaneously, and you can edit the properties of the x and y axes to display the grid lines as closely as you desire as shown
below.

In some cases you can have curves with complicated shapes that you may want to investigate in details. The zoom tool is handy for that. When you press the toolbar button
with the little magnifying glass, zoom mode switches on, and you can select an area of the chart for closer investigation by dragging the mouse. You can zoom again on the
zoomed area and go as close to the detail you are interested in as you like. The zoom mode remains active until you click the magnifying glass again. This resets the view
to the original area.

To investigate the data in even more detail you can switch the data box on by clicking the appropriate button on the toolbar. This gives you a spreadsheet-like box at the
bottom of the screen, and you can investigate the numbers behind the graphs in detail. You can even double-click the numbers and edit them. Of course, that would be
cheating...

The specification line

Above the toolbar in the chart view you find a specification panel. It is useful for several applications that are a bit more advanced. With the specification panel you can
specify plotting of a family of curves, you can specify your own abscissa, and you can save and recall plot specifications.

You may want to look at several curves at a time. The secret to doing that is the Y data specification line. This line can to some extent parse the specification string. This
means that you can compose the string with any number of wild characters such as you may know from file name specifications in Windows, Unix and other operative

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 40 of 229

systems. If you, for instance, replace "brachialis" the data specification with '*' like this:

ArmStudy.Output.Model.Muscles.*.Fm

then you will get all the muscle force curves plotted simultaneously. as shown below:

We have eight muscles in this model, so why do you only see two curves? The explanation is that all the muscles in this model have the same strength, so they team up in
groups where all the muscles pull exactly the same. This model has three groups. The brown curve at the top, the green curve in the middle, and another green curve of
inactive muscles on the x axis. So several curves are hidden under each of the curves you can see.

As you can see, the legend box at the bottom of the window only shows one muscle. This is because the muscle names are rather long, and the box simply does not have
room for more. However the box is dockable, and you can place it anywhere you like, including in its own window outside the Chart View, and you can resize it until it fits
the legends you want to display, for instance as shown below:

User-defined abscissa

The default abscissa in the chart view is time. However, you can in principle plot data against any scalar property the system has computed. Let us imagine that the
dumbbell curl study we are looking at is an ergonomic investigation of the effort of lifting the weight to different heights. In that case, it might be more relevant to plot the
muscle force as a function of the height of the hand. The way to do so is simply to replace the ArmStudy.Output.Abscissa.t specification in the X specification line. Let us
start by finding the position of the hand. If you browse down the tree through Main.Model.Segs.LowerArm.Handnode.r. You will get three graphs:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 41 of 229

The three graphs (of which one is constant zero) is because the hand node position is a vector with three coordinates. We want to extract the height, which is the y
coordinate, and use it as the abscissa. But the abscissa obviously cannot be a vector, so we must construct a scalar variable containing the y coordinate of the hand node in
the AnyScript model. The way to do so represents a very useful and slightly subtle trick, and requires a bit of explanation.

At the beginning of this lesson you learned that the system automatically defines a group of variables containing the output from the analysis. But you can also define your
own output variables. The only difference between an output variable and an ordinary AnyVar is that the values of output variables get stored for each time step.

So how can we make the system perceive a given variable as an output variable? The answer is that any variable defined inside an operation in a study is a user-defined
output variable. Now we are getting to the point of the case at hand: We can define the y coordinate of the HandNode as a variable in the InverseDynamicAnalysis
operation in the study and subsequently use it as the abscissa of the Chart View. Here's what to do:

AnyBodyStudy ArmStudy = {
AnyFolder &Model = .ArmModel;
InverseDynamics.Criterion.Type = MR_MinMaxStrict;
Gravity = {0.0, -9.81, 0.0};
InverseDynamicAnalysis = {
AnyVar HandHeight = Main.ArmModel.Segs.LowerArm.HandNode.r[1];
};
};

As you can see, the new code is an addition to the existing (implicitly defined) InverseDynamicAnalysis object. The result is that the model now contains a scalar output
variable called HandHeight containing the y coordinate of the handle. Try adding that piece of code to the model, reload, and run the InverseDynamicAnalysis. You should
now have the following section in the tree in the Chart View:

As you can see, the tree has been extended with the new variable we have defined. The next step is to use this variable as the abscissa.

Notice the first line of the panel above. It holds the time specification, but it is grayed out, and you cannot write anything in the field. To be able to change this line, first
click the "Out" button. "Out" means that this is where to click if you want to select a new abscissa among the output variables. Clicking the button changes its name to
"Auto" and ungrayes the line. Now you can place the cursor by clicking somewhere on the formerly gray line and subsequently browse your way in the tree to the
HandHeight variable and click it. This places the variable in the X specification, and it is now used as the abscissa of the graph.

Stacking graphs

As you have seen, getting the specifications of a graph completely right can sometimes require a some amount of clicking around in the tree and in the specification panel.
So some way to save your carefully selected plot specifications can be handy. The specification panel allows you to put your carefully selected graphs on a stack and to
recall them when you want them back. Whenever you click the "Ins" button the current graph is inserted into the stack and given a number. By means of the "<<" and ">>"
buttons you can scroll back and forth between the plots you have saved. The "Del" button removes the current graph from the stack.

Exporting data

You are almost bound to want to save your data in various ways. Perhaps you want to save a graph for inclusion in a report you are writing. Perhaps you desire to save the
chart on a compact format for later review without having to run the AnyBody analysis again. Perhaps you want to export the data to a text file for processing by statistical
software. Or perhaps you want to paste the data into a spreadsheet to make customized combinations of data for presentation in customized graph types.

The Chart View has its own file format that you can save and load. The files have extension .CHT, and they are very compact and easy

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 42 of 229

to store and exchange. You Open and Save .CHT files with the first two buttons on the toolbar. A stored .CHT file can be sent to other
AnyBody users, and they can load it in and investigate the results you have produced. Please notice that a loaded .CHT file is only computational data. It has no connection
to the model that generated the output data, and you do not get the model loaded when you load the .CHT file.

.CHT files are a convenient way of storing analysis data because they can subsequently be reformatted and displayed in other ways than you initially planned, for instance a
stacked column diagram or a pie chart instead of curves.

Data can also be exported from the Chart View via the clipboard. The "Copy to clipboard" icon on the toolbar gives you the opportunity to copy the present chart on
different formats:

 As a bitmap picture. The picture will have screen resolution, so the quality depends on the size of the Model View. For maximum quality, maximize the AnyBody
Modeling System main frame on your desktop and maximize the Chart View inside the main frame.
 As a vector-based windows meta file. This type of file has infinite resolution, so you can scale it up and down without loss of quality. However, this requires that the
application into which you intend to import the file supports vector graphics.
 As a windows object. This option is currently not active.
 As a text. This option copies the graphed numbers to the clipboard on text format, and you can subsequently paste them into a spreadsheet or a text editor. Pasting
into a spreadsheet can be very useful because it allows you to use the data in subsequent processing such as statistical analysis.

A word of caution regarding the the text option: Different countries have different conventions for decimal numbers. Some use a point as decimal separator, and some use a
comma. The numbers copied to the clipboard from the Chart View follow the nationality settings for decimal point or comma. When you subsequently paste the numbers
into a spreadsheet it is important that the spreadsheet follows the same conventions. If the numbers coming out of the Chart View for instance use decimal comma and the
spreadsheet receiving them expects number with decimal points, then the spreadsheet will interpret the numbers you paste in as text rather than numbers.

The AnyChart View

AnyChart is AnyBody's alternative for making charts. AnyChart is special compared to ChartFX in the way that AnyChart uses the AnyScript class called AnyChart to
make the visualization. The AnyScript class AnyChart is a draw object that can be used in the AnyScript code to make charts in the Model View of the model. The
AnyChart View wraps the features of the AnyChart class into a window in the AnyBody GUI. Currently, AnyChart pocesses only simple charting features, and therefore
AnyChart and ChartFX still lives side-by-side in the system.

AnyChart collects all its properties as described for the AnyChart class in the AnyScript Reference Manual. In contrast to ChartFX, all these properties are saved in
workspace files, so AnyChart Views are generally reestablished better, when introduced into workspaces.

AnyChart is AnyBody's only tool for showing 3-D surfaces. One main difference between AnyChart and ChartFX is that AnyChart allows you to define two Abscissa axes.
AnyChart is mainly used in conjunction with parameter studies and optimization. Please refer to the Parameter Studies and Optimization tutorial for a demostration of these
features.

AnyChart also introduces multiple series in the same chart. The primary mechanism of selecting values to be depicted in the chart is the same as for ChartFX, but with
multiple series you can add several selections together in the same chart.

One additional small difference between the charts is AnyChart's selection line also that allows you select elements of vectors, matrices, and higher order tensors. Like in
AnyScript code, [] bracket can be used to select subelements.

The next interface lesson is concerned with a part of the system that really has a minimum interface: The command line version .

Lesson 5: The Command Line Application


The AnyBody Modeling System comes with a command line version included. It is named AnyBodyCon.exe ("Con" for console application), and you will find it in the
directory where you install AnyBody. The command line version is - as the name indicates - a version of the AnyBody Modeling System with the user interface stripped
off. This means that it is executed from a DOS command prompt or - more importantly - by a batch file or another software application.

As you may suspect from that introduction, the command line version is mostly designed for technical users wishing to set up their own data processing application by
piecing different types of software together.

The console application can either work interactively and accepts commands that you type in response to its command prompt, or it can take its input from a file containing
macro commands. Let us try the interactive mode. We need a model to work on, so please download and save Demo.outputfile.any in some working directory.

Here's a tricky part: AnyBodyCon does currently not have any commands for changing the working directory after it has been started. Therefore, it must be started in a way
so that it can find the model files you intend to load. You can basically do this in two ways from a DOS prompt:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 43 of 229

1. You change directory to wherever you saved Demo.outputfile.any and from here you run the console program using its full path, e.g. "C:\Program Files\AnyBody
Technology\AnyBody.3.0\AnyBodyCon.exe" .
2. You open AnyBody with a /d argument that sets the working directory of console. You can either change the directory to the place of AnyBodyCon.exe first or you
can use the full path from anywhere, e.g. "C:\Program Files\AnyBody Technology\AnyBody.3.0\AnyBodyCon.exe" /d "c:\...\My Documents"

Naturally, you can add the path of AnyBodyCon.exe to the path of your DOS command prompt environment, but be aware that this can cause confusion in case of multiple
installations of AnyBody. We shall cover this issue of using DOS PATH in more details in a separate section later in this lesson.

You are now ready to use the console application. The application is rather primitive. It only understands eight different commands. You also always get help by using the
'help' command or by calling AnyBodyCon with /? argument. The latter approach will give you the full help including descriptions of the possible program arguments. The
table below contain a description of the commands accepted by the AnyBody console.

Command name Functionality


Example: load "demo.outputfile.any"
load "filename.any"
This command loads an AnyScript model into the system and compiles it. Don't forget to put the filename between
double quotes.
Example: operation Main.ArmStudy.InverseDynamics
operation <op.name>
This command sets the active operation. This is what you must do as the first thing after you load a model. All the
remaining commands except exit require an active operation to work on.
Example: run
run
This command takes no arguments. It simply runs the active operation.
Example: step
step
This command takes no arguments. It performs a single step of the active operation.
Example: reset
reset
This command takes no arguments. It resets the active operation.
Example: print Main.ArmModel.Jnts.Shoulder.Pos
print <object>
This command prints the value of a single variable. If the variable is a folder, it just lists the names of the element of
the folder.
Example: printdown Main.ArmModel.Jnts
printdown <object>
This command recursively prints the values of all elements in an entire folder.
Example: Exit
exit
This command exits anybodycon.exe and returns to the dos command prompt.

Now let us try the console application. Start AnyBodyCon.exe from the command prompt and issue the command sequence:

load "demo.outputfile.any"
operation Main.ArmStudy.InverseDynamics
run
exit

You will see the system write a whole lot of messages about the progress of the computation. It is not nearly as interesting as running the Windows version of the AnyBody
Modeling System. So why bother?

Well, the command line version of the AnyBody Modeling System faithfully performs all the computations you ask it to through the command line. But what good does it
do you, and how can you access the results? You could issue print or printdown commands and have the results listed on the screen. It would give you a whole lot of
probably completely useless numbers to look at.

A more clever way to use the command line version is to insert AnyOutputFile objects into the AnyScript model. If you load the demo.outputfile.any model you have just
worked on into the Windows version of the AnyBody Modeling System, you will notice that it contains two definitions of AnyOutputFile objects inside the ArmStudy.

// The study: Operations to be performed on the model


AnyBodyStudy ArmStudy = {
AnyFolder &Model = .ArmModel;
InverseDynamics.Criterion.Type = MR_MinMaxStrict;
Gravity = {0.0, -9.81, 0.0};

AnyOutputFile OutFile1 = {
FileName = "out1.csv";

AnyVar MaxAct = .MaxMuscleActivity;

AnyFloat TestTensorConst = {
{1, 2, 3},
{1, 2, 3}
};

AnyFloat TestTensor = {
{
{1, 2, 3},
{1, 2, 3}*2,
{1, 2, 3}*3,
{1, 2, 3}*MaxAct

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 44 of 229

},
{
{1, 2, 3},
{1, 2, 3}*2,
{1, 2, 3}*3,
{1, 2, 3}*MaxAct
}
};
};

AnyOutputFile OutFile2 = {
FileName = "out2.csv";
Search = {"ArmModel.Muscles.*.Act*", "ArmModel.Muscles.*.Ft"};
SepSign = ";";
};
};

Furthermore, if you open a file manager and look at the contents of the directory where you are running the problem, you will notice that two new files have been
generated: out1.csv and out2.csv. They are comma-separated files with a semicolon as separator between numbers as defined in the AnyOutputFile above.

If you have software on your computer that is associated with csv files, such as Microsoft Excel, then you can double-click any of the two files and open it. You will notice
that it contains columns of data dumped from the analysis. The precise nature of the data is defined in the file's header, and it has been determined by the variables defined
inside the corresponding AnyOutputFile object. Please refer to the reference manual for further information.

As you can see, the command line version can produce output data that can be formatted according to your desire and processed further by other types of software. But the
really great thing about the console application is that you can execute it from other software such as Matlab or Visual Basic and as such build it into an integrated system
for large-scale biomechanical data processing such as response surface-based optimization. Instead of typing the commands into the application by hand, you can store
them in a macro file. Such files usually have the extension ".anymcr". The command line application can be given such a file as its command line argument, and it will
perform the commands in it. Don't forget to make "exit" the final command of the macro file if you want the application to end after processing the macro file.

You are now ready to let the command line application be a part of a system for biomechanical data processing of your own design.

Path specification

As mentioned earlier, you can add the path of AnyBodyCon.exe to the path enviromental variable for your DOS prompt to ease the call to AnyBodyCon.exe from
anywhere. This you can do from the DOS prompt with a statement such as

path c:\Program Files\AnyBody Technology\AnyBody.3.0\;

or

path %path%;c:\Program Files\AnyBody Technology\AnyBody.3.0\;

if you want to add the AnyBodyCon.exe's path to the exisitng path definition. Notice that you cannot have any space between ';' and the following path "c:\..." and that you
can see the resulting path by simply calling the internal path command again without arguments.

These statements will only take effect until the current DOS prompt is closed, but you can also add the path of AnyBodyCon.exe permanently to the path for all DOS
prompts. In Windows XP for instance, you do this from Control Panel -> System under the Advanced tab. You should however be aware that multiple versions of
AnyBody may be installed on the computer at the same time, and therefore, multiple versions of AnyBodyCon.exe may exist in different locations. Thus, your path
specification not only make it easy to call AnyBodyCon.exe; it will also specify which version that will be used. This can make unclear which one you are actually using if
you need several of them.

To be in full control with multiple installations of AnyBody, you can define aliases by the following procedure

1. Make a directory with .bat files or shortcut to the AnyBodyCon.exe version you will need. Name the bat-files properly, so you can recognize the different version,
e.g. AnyBodyCon201.bat and AnyBodyCon30.bat. The bat files contain a single statement, the call of AnyBodyCon.exe with its full path.
2. Add this directory to the permanent path of the DOS prompt.
3. You can now call the different versions of AnyBodyCon via the bat files, so the bat file names are working as aliases for the real exe files.

Lesson 6: Browsing the Model via Model Tree and Object Description
A large AnyScript model, such as any application that employ full or partial body models of the AMMR repository, is difficult to get an overview of if you are very
experienced in AnyScript and/or know the repository models very well.

The following issues are each a contributors to making models harder to understand, albeit these are functions that provide AnyScript some of its power for making
advanced and versatile models

 #include files can be used more than one time and therefore there is not a one-to-one correspondence between AnyScript code and the resulting Model Tree
 Folder objects can be initialized many times in the code. This implies that member of a folder can come from very different places in the code, hereunder different
files.
 AnyScript references (reference objects) can point to objects from other places in the code; a reference will, for many purposes, work as a local object, even though
the real object is actually located “far away”. AnyScript references are often used for making simple and clear interface between part of the code (instead of writing
the same long path many times, you use a reference objects created once as a substitution of the path).

In this lesson, we look at the features in the AnyBody Modeling System that can assist you in finding your way around the advanced models.

The Model Tree


The basic feature for browsing the model is the Model Tree, which you find to the left in the AnyBody Modeling System GUI. Additional Model Trees can be opened on
the left hand side of each AnyScript Editor Window. There are no significant differences between the Model Tree in these two locations, but if your work is related to

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 45 of 229

many places in the code, it can be practical to work with multiple Model Trees opened.

The Model Tree of a well-structured model provides a good overview of the model, but for large models the Model Tree will become large and deep, and even using
several Model Tree view, it can be difficult to navigate around in the model only with the Model Tree. It should however be emphasized that the Model Tree is the proper
starting point for navigating around in the model, in particular if it is a model you do not know in advance.

Basically, the other UI features, we shall get to know in this lesson, are links that allow you to jump around in the Model Tree and to the AnyScript source code according
to the dependencies in the model. This can become a powerful tool for navigating around in and browsing the model both for the person who is new to a model and for the
person who built the model and know it by heart.

‘Locate in AnyScript’ and ‘Locate in Model Tree’


From the context menu (right-click) for any object in the Model Tree, you have an option for “Locate in AnyScript”. This is a link to the AnyScript code of the object.

However, you should be aware of two things about the Locate-functions:

 The code location you arrive at may also be the code for other objects in the model. Reuse (multiple use) of a source file via multiple #include statements will lead to
this. For instance the right and left hand sides of the human model in AMMR are using the same source files. Thus, jumping to the code location and editing requires
one to be aware of the implications.
 Multiple initializations of an object (folders only) imply that an object may have multiple code locations. An object can have only one so-called construction
location, i.e., the place of declaration, and multiple initialization locations. If an object has indeed multiple code locations associated, a selection box will appear
requiring you to select the location you want (Or you can keep trying until you find what you are looking for).

Being in the source code, i.e., in the AnyScript Editor Window, you may wish to go back to the Model Tree for further browsing. You may have encountered an expression
or a reference declaration pointing to objects in other parts of the model. In such cases you can highlight (mark) the object name in the text and the context menu (right-
click) provides you with the option “Locate in Model Tree”.

This option may also open a selection box for you to select between possible objects; in this case because one place in the code may correspond to multiple places in the
Model Tree.

The “Locate in AnyScript” and “Locate in Model Tree” are the two basic links between Model Tree and AnyScript source code and with some experience they provide a
good tool for jumping around in the model. However, you will find similar links in many other places of the system.

For instance, you will find both “Locate…“ options in context menu of the Model View. Right-click an object in the Model View and the context menu appear.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 46 of 229

Notice that an object in Model View is often related to multiple objects in the Model Tree. For instance a drawing object inserted for displaying a certain bone should
provide you with a link to the drawing object itself when you work with the display of the model; but when you work with the mechanics of the model you rather need a
link to the mechanical segment, which the bone draw object typically will be attached to.

In order to accommodate for such different needs, the lower part of the Model View context menu provide you with all relevant objects in the branch of your selection.
With this you can hopefully select what you need to find. One deeper level of the context menu reveal the “Locate in AnyScript” and “Locate in Model Tree” link options
again.

Hyperlinks to the Model Tree and AnyScript Source


In many places of the AnyBody Modeling System, you will find text view with hyperlinks. You basically find two types of links

 Object names with links for the Model Tree


 File locations linked to the AnyScript source

These links are basically the same as the ones you follow with the “Locate in AnyScript” and “Locate in Model Tree” link options. You find this kind of links in the Output

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 47 of 229

View in bottom part of the screen for instance as integral part of the error/warning messages.

The Object Description


The Object Description is another hyperlinked text view. Basically it is created by a so-called Class Operation that all classes are equipped with (i.e. a Class Operation of
AnyObject, the root class for all AnyScript classes). The Class Operation writes a lot of basic and important information about the objects and the aim of this information is
to assist you in understanding the model and browsing it.

The Object Description is opened from the context menu of an object in the Model Tree. Double-clicking an object in the Model Tree will also open it and moreover the
new (version 5.0) pane to the right of the Main Model Tree also shows the Object Description.

The Object Description basically looks like above. It contains a header with hyperlinks to the Model Tree and to the source, in particular the construction location.
Furthermore, you find a value section and a comment section.

In the case above the value section is empty because it is a folder object, i.e. a holder of other objects, but not a particular value.

The Comments section contains the so-called Documentation Comments, which are made in the AnyScript source; please refer to the AnyScript Reference Manual for
more details on Documentation Comments and how to make them. However, do notice that they can be placed before and after an object’s initialization in the code, and for
folder objects also in the middle of their scopes. This allows the model builder to provide comments that are readable to the user in the source code as well as from the
Object Description. Moreover, these comments may functions as bookmarks for important places in the code, since the Documentation Comments each have links to their
particular source code location.

Objects with a particular value provide more details about the current value in the value section of the Object Description. A file-object (class AnyFile) for instance will
provide an Object Description like this:

Other value objects provide information such as current numerical value, symbolic expressions/dependencies, expression evaluation timing, etc. This is a place to collect
all important information available and it can be expected to be further enhanced in future versions of AnyBody.

Objects with higher level of abstraction, such mechanical objects, operations, studies, etc., may provide additional information in the Object Description. Below is a picture
of the Object Description of a musculoskeletal study (class AnyBodyStudy):

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 48 of 229

Notice how the Comments section is followed by a System Description section that is filled by the study-object’s information about the mechanical system to be analyzed;
all equipped with hyperlinks to elements such as segments, joints and other kinematic elements, forces, etc.

Now a study is about the highest level object that exists in the model, but even “lesser” objects, such and kinematics joints will provide information on what it connects,
etc.

Understanding the Object Description and the information in it can be a powerful tool for understanding and browsing the model.

This concludes this lesson on browsing the model. The next lesson is Lesson 7: Modifying the Loaded Model .

Lesson 7: Modifying the Loaded Model


AnyBody, version 4.2.x provided the first very simple facilities to modify the model after it had been loaded. This aimed at saving loading time for certain modifications,
typically while adjusting parameters manually, and then it aimed for future extension. AnyBody, version 5.0, provides the next generation of these features. In this lesson
we shall take a look at these facilities, but first let us understand the difficulties of this topic.

 Modification of a value in the model needs to be followed by some action. Originally, the only operations accessible to the user are “operations” (class
AnyOperation), such “Set Initial Conditions”, and “Kinematic Analysis” of mechanical studies, and Class Operations of objects. This implies that modifying a value
does not imply that all dependencies are updated; not unless you execute an operation that performs such updating.
 Having modified a value does not bring it into the AnyScript source code and as such the modification is lost if you load the model again. Saving it back to the code
is generally not possible since there is not a one-to-one correspondence between Model Objects and code; two or more objects may come from the same code. There
are, however, options for storing modified values, and we shall look into these in this lesson.
 Values in the AnyScript source have different accessibility. Some you cannot initialize, neither in the AnyScript source nor afterwards; these are controlled entirely
by the algorithms of the program and thereby by the operations you execute on the model. Other values are initialized in the source code; some of these may be
constants while others are symbolically dependent on others. Symbolical dependencies are updated during operations on the model and a good question is then what
happens if you modify a value that are symbolical dependent on other values? Or can you actually do this at all? We shall look into this below.

Setting Values
Setting values is basically done by the Model Tree context menu option called “Set Value”. It is of course only available for value-holding objects (objects of classes
derived from AnyValue) and it is only active for value-objects that are allowed to be edited. In the Model Tree, this is clearly marked.

Having set a new value will have no other immediate effect than the given value being changed; no dependencies are automatically updated. Executing an operation will
update all symbolic expressions and internal algorithms as they normally do and thus the effect of the change will appear running a suitable operation. But please recall that
even operations/studies may operate on a part of the model only.

As a Class Operation, “Set Value” is also available from the console application interface. Moreover, it is also being wrapped by so-called AnyScript-Widgets.

AnyBody, v. 5.0 introduces two AnyDrawWidgets that allows you to interact with values via the Model View. These widgets are objects that must be defined in the model
and that point to a certain model target value, i.e., the destination for your modification. The AnyDrawWidgetLin manipulates 3D vectors and AnyDrawWidgetRot
manipulates rotations, targeting rotational transformation matrices and such. The widgets are also equipped with a pointer to an operation which will be executed at certain
update events. As such widgets are a tool that modify (“Set Value”) values but also updates them in order to provide some feedback to the user during the modification. We
shall not go into more details with drawing-widgets at this stage.

Symbolic Dependencies
In a simplest logic, setting the value of an object with a symbolic dependency would only allow the value to live until next update, which would imply that such
modifications would never have any effect since values are updated before used. Therefore setting values of objects with symbolic dependencies were not allowed before
AnyBody, v.5.0.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 49 of 229

From AnyBody, v.5.0, it is however allowed. Symbolic dependencies can be broken and if so they are marked as broken and will not be updated anymore. This is a
potential dangerous action that can dramatically change the behavior of the model, and therefore value-objects with such symbolic dependencies are clearly marked with an
additional ‘*’ in the Model Tree and modifications are followed by a warning.

Resetting Symbolic Dependencies

The Class Operation “Reset Value” can be used to re-establish the intended behavior from the source code as well as original values.

Resetting can also be done from the Main-folder via its Class Operation called “Reset Values”, which will reset all values in the model. This action is also available from
the menu Operations > Reset All Values, where you will also find other operations we shall consider below.

Updating Symbolic Dependencies

As already explained symbolic dependencies are not updated except by running a suitable operation. In order to allow extended and easy user control, the Main folder is
equipped with a Class Operation called “Update Values”. This will do an update of all symbolic expressions in the model so they will reflect the modified input. This
operation will however not perform any of the programs algorithmic updating.

As a Class Operation, this can be embedded into normal AnyScript operations (by use of the AnyOperationMacro) and it can be called from the console application
interface. Moreover, it is also available from the menu Operations->Update All Values (see also the image above).

Storing Modified Values – Saving and Loading Values


As explained initially, modified values are not saved back into the AnyScript source code, and in the generally case this is not possible. However, the Main-folder is
equipped with two Class Operations, one for saving (“Save Values”) and one for loading values (“Load Values”). These functions are also available from the menu
Operations->Save Modified Values and Operations->Load Modified Values, respectively.

The saving operation saves all values having been marked as modified into a file. It is a simple AnyScript like text-based file that can be opened and modified in a
text/AnyScript editor. Also it can be included into the model source, at least if the values are not initialized in the original code (or this initialization is removed).

The file can later be read into the same model (or a similar model) by the loading operation. This operation will load all the value in the same objects (by using complete
name) and it will mark all these value-objects as modified. It will basically be as if you apply “Set Value” manually to all the value-objects in question. This implies that no
automatic updating is carried out by the loading operation.

Lesson 8: Wrapping the Model with AnyBody Project


“AnyBody Project” or just AnyProject, since it is defined with this class name, is a data structure aimed at wrapping a model and bringing its important features to the
surface in AnyBody GUI and thereby closer to the user.

The aim is to ease execution of important model’s operations and related actions and collect these in an dedicated and intuitive place. This is equally aimed at the
experienced and advanced user doing repetitive work with many models or many data sets, users working with models prepared by others, and the less experienced users
who need to work with a model for processing data but does not have to develop it r understand its every detail.

AnyProject was introduced in AnyBody, v.5.0, and currently its functions can be summarized by

 Model View Definitions that provide features for defining particular views of the model and user interface for activating the views.
 Task definitions that wrap the important operations of the model with a user interface for execution. A Model View Definition can be associated with a given task.
 All project objects are equipped with descriptions that can be used for explaining the task or view to new users.
 Project file information is automatically found by the system and can be supplemented by the user.
 “Send to” function for exporting the model and all of its resources to a new location

An AnyBody project is defined in the model, in principle like any other objects of the model using the AnyProject class. The main difference to most objects is that project
objects do not provide new information by themselves, but merely collect information to the AnyBody Modeling System GUI about what is important in the particular
model.

In this lesson we shall make an AnyBody Project wrapper of the very simple planar arm model ( Demo.arm2d.any using dumbbell.stl ) that we have used in previous
lessons. The final example file we shall build in this lesson is AnyProject.any using DrawGroups.any in addition.

We include the model file in our new main file and we make an empty project called ArmProject.

Main = {

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 50 of 229

#include "Demo.arm2d.any"

AnyProject ArmProject = {
};

}; // Main

Project Files
Firstly, we add some file information to the project. This is done in the AnyProject Files folder, which is a predefined folder. Here we set two files, the MainFile and the
SetValueFile.

Main = {
#include "Demo.arm2d.any"

AnyProject ArmProject = {

Files = {
MainFile = "AnyProject.any";

SetValueFile = "values.anyset";
};
};

}; // Main

The MainFile indicates simply which file is the main file for this project. It may seem a bit redundant, but this information also serves to determine whether the project is
active or not. Multiple projects can in principle exist in the model, but only the one(s) having the correct main file is considered active by the system.

This implies that we can include a file that is actually a Main file by itself (as in this case with Demo.arm2d.any) and this main file could in fact have a project
(AnyProject) of its own, but it would only be active, if we actually load the arm2d.any. In the given example we have only one AnyProject.

The SetValueFile is a file used by the project for storing modified values. It is automatically saved when closing the model and automatically loaded, although only upon
user acceptance, when loading the model. Apart from this, it is saved and loaded exactly like the manual execution of the Main folder’s Class Operations, “Save Values”
and “Load Values”, respectively.

The SetValueFile needs not to be specified and it will only be managed by active projects, i.e. project with a MainFile specification matching the loaded Main file.

The Files folder also contains some file-objects for storing project file information. These are automatically filled during loading. Their information can of course be
accessed or just inspected by the user, but it is also used during “Send to” export operations on the model (Class Operation of Main). It should however be noticed that the
“Send to” Class Operation to some extent is functional for models without project information too.

Model View Definitions


Model View Definitions are basically a set of view actions applied to a number of drawing groups. In order to set up some standard views for the model, we shall therefore
define some drawing groups:

Main = {
...

AnyFolder DrawGroups = {

AnyDrawGroup AllSegments = {
Objects = ObjSearch("Main.ArmModel.Segs.*");
};

AnyDrawGroup AllMuscles = {
Objects = ObjSearch("Main.ArmModel.Muscles.*");
};

AnyDrawGroup AllDeltoidMuscles = {
Objects = ObjSearch("Main.ArmModel.Muscles.Del*.DrwMus");
};

AnyDrawGroup All = {
Objects = ObjSearchRecursive("Main.ArmModel","*");
};

};

...
}; // Main

In the final example files, this is actually done in a separate file, DrawGroups.any , so we now have

Main = {
#include "Demo.arm2d.any"
#include "DrawGroups.any"

AnyProject ArmProject = {

Files = {
MainFile = "AnyProject.any";

SetValueFile = "values.anyset";
};
};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 51 of 229

}; // Main

Having defined the draw groups we need, we can return to the project definition and define our view

Main = {
#include "Demo.arm2d.any"
#include "DrawGroups.any"

AnyProject ArmProject = {

Views = {
AnyProjectModelViewDefinition View_Misc = {
DrawGroupSequence = {
&Main.DrawGroups.AllSegments,
&Main.DrawGroups.AllMuscles,
&Main.DrawGroups.AllDeltoidMuscles
};
Reset = {Off, Off, Off}; //Same behavior as not defining Reset.
Hide = {Off, Off, Off}; //Same behavior as not defining Hide.
ShowModelDefined = {On, Off, On};
ShowAutoGenerated = {Off, On, Off}; //Same behavior as {Off, On}.
Transparent = {On, Off, On};
Select = {Off, Off, Off}; //Same behavior as not defining Select.
};
};
...

This view we define using three draw groups, all segments, all muscles and the deltoid muscles. We want to show the model-defined segments and deltoid muscle being
transparent and the rest of the muscles will just show their default drawing. The result you can see below, where all the muscles, except deltoid’s two branches, are marked
with the “AF” indicating an “Applied Force”, which is their current default (auto-generated) draw object.

In the final example model you can download, we have defined three other views, just to show how it works. For further information on how to define Model View
Definitions, please refer to the Reference Manual.

Project Tasks
Firstly, we define two simple tasks that execute the two important operations of our main (our only) study. It executes the setting of initial positions and inverse dynamics.
These tasks are created by defining two AnyProjectTaskOperation objects that point to the particular operations in ArmModelStudy.

Main = {
#include "Demo.arm2d.any"
#include "DrawGroups.any"

AnyProject ArmProject = {

Tasks = {

AnyProjectTaskOperation Set_Initial_Conditions = {
Description = {
Title = "Initial Conditions of Arm Model";
BodyText = "This task sets the initial conditions.";
Tooltip = "Sets Initial Conditions";
Files = {"dumbbell.stl","values.anyset"};
};
Operation = &Main.ArmModelStudy.InitialConditions;
};

AnyProjectTaskOperation Run_Inverse_Dynamics = {
Description = {
Title = "Inverse Dynamcis of Arm Model";
BodyText = "This task executes the inverse dynamics analysis of the arm model.";
Tooltip = "Inverse Dynamics Simulation";
};
Operation = &Main.ArmModelStudy.InverseDynamics;
};
};
...

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 52 of 229

Each task is accompanied with a description consisting of a title, a body text, and a tooltip string. All strings will appear in the AnyBody GUI in the Projects pane.
Additionally, the description can hold a list of files. Here we have just added links to some file that are already part of the model, but a more relevant case could be to make
links to external documentation related to the given task and model.

In addition to these options for executing the model, we want to equip the model with tasks for saving and loading the simulated output. This can be done by declaring
AnyOperationMacro object that calls the Class Operations for “Save data” and “Load data” on the output-folder for MainArmModel.Study. All this, we do inside the task
folder definition because it is not part of the original model, see the following code:

Main = {
#include "Demo.arm2d.any"
#include "DrawGroups.any"

AnyProject ArmProject = {

Tasks = {
...

AnyProjectTaskOperation Save_Output_Data = {
Description = {
Title = "Saving output data from the simulation";
BodyText = "This task saves the output for the simulation, e.g. executed by task " +
strquote( AnyBodyLinkOf(&..Run_Inverse_Dynamics) )
+ " to file "
+ strquote( strlink(.filename) )
;
Tooltip = "Saving output data";
Files = .filename;
};
Operation = &Opr;

AnyFileVar filename = FileNameOf(..Files.MainFile) + ".anydata.h5";

AnyOperationMacro Opr = {
MacroStr = {
//"classoperation Main.ArmStudy1.Output" + " " + strquote("Save data"),
("classoperation Main.ArmStudy1.Output" + " " + strquote("Save data")
+ " --file=" + strquote(FilePathCompleteOf(.filename)) + " --type=Deep")
};
};
};

AnyProjectTaskOperation Load_Output_Data = {
Description = {
Title = "Loading output data from a previous simulation";
BodyText = "This task load output saved by the task " +
strquote( AnyBodyLinkOf(&..Save_Output_Data) )
+ " from file "
+ strquote( strlink(.filename) )
;
Tooltip = "Loading output data";
//Files = .filename;
};
Operation = &Opr;
AnyFileVar filename = .Save_Output_Data.filename;

AnyOperationMacro Opr = {
MacroStr = {
"classoperation Main.ArmStudy1.Output" + " " + strquote("Load data")
+ " --file=" + strquote(FilePathCompleteOf(.filename))
};
};
};

...
};
...

Finally, a special task is demonstrated, namely AnyProjectTaskLoadModel . It can load models and here, we shall indeed make an operation that loads the model without
any project definition. In other words, we create an AnyProjectTaskLoadModel that loads the Demo.arm2d.any, but without the AnyProject.any master file.

Main = {
#include "Demo.arm2d.any"
#include "DrawGroups.any"

AnyProject ArmProject = {

Tasks = {
...
AnyProjectTaskLoadModel Load_the_model_without_project = {
MainFile = "Demo.arm2d.any";
};
};
...

The practical relevance of this particular load task may be hard to see, but it illustrates the option of loading another model from one already loaded.

A more relevant case could have been to share the project-source code between two or more different Main file, so that loading another Main file would leave the project
information, such as Tasks and Views, more or less unaffected, even though the loaded model is shifted. This way a Task flow that requires more than one model can in
principle be bound together in the same user interface.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 53 of 229

A Study of Studies
Studies and operations are AnyBody's mechanisms for specifying "things to do to the model". The study is the “collector“, in the sense that a study collects a model
definition with the operations that executes the model and the results to investigate afterwards. Operations are the things you can do to the model; they can be executed
from the AnyBody interface and while they run output is generated and stored in the study according to the function of the specific operation.

Why does AnyBody have studies? You might expect that you could just load a model and then operations would simply be available in the AnyBody interface. But why
are studies then defined as special classes? Why do you need to declare then manually in the model?

The reason to have studies as a special class is basically that you can have multiple studies in the same model. Since studies become objects in the model, there can be as
many as you need (or your computer can manage which is depending on the model size) and they do not need to comprise (operate on) the same model definition even
though they share elements.

A simple example of the usage of multiple studies is to perform to different operations on the same model, or to perform the same operation on almost equivalent models,
and subsequently comparing the results. With two studies, this can be done in a single AnyBody model.

Studies are derived from the base class called AnyStudy and the operations you find inside the studies are also defined as class; all derived from the base class
AnyOperation.

AnyBody's family of study classes looks like this:

 AnyStudy (Base class for all studies)



 AnyTimeStudy (Base class for time variation studies)

 AnyMechStudyBase

 AnyKinStudy

 AnyMechStudy
 AnyBodyStudy
 AnyBodyCalibrationStudy
 AnyMechStudy1 ( deprecated! )

 AnyBodyStudy1 ( deprecated! )
 AnyDesStudy (design variable studies, see a separate tutorial )

In this tutorial, we shall focus on time varying studies and in particular mechanical studies that deal with the analysis of mechanical system. The other major branch of
studies are design studies that deal with variations of design parameters for instance as parameter studies and even optimization. A special tutorial is however devoted to
this topic typically design studies will build on top of the analyses performed by other studies, such as mechanical studies.

The mechanical studies (derived from AnyMechStudyBase) are all very similar, except that they contain different sets of available operations. The base class is empty;
AnyKinStudy extents this with functionality for kinematic analysis. AnyMechStudy further extents this with kinetic (dynamic) analysis of basic mechanical systems.

AnyBodyStudy is the must frequently used study by AnyBody users, since this study extents the kinematic analysis functions with operations for kinetic (dynamic)
analysis of musculoskeletal systems, i.e., the core functionality of the AnyBody Modeling System. AnyBodyCalibrationStudy contains assisting functionality in this regard.

AnyMechStudy1 and AnyBodyStudy1 are deprecated versions of AnyMechStudy and AnyBodyStudy, respectively, and we shall not consider these any further in this
tutorial.

In this tutorial, we shall use AnyBodyStudy as starting point because of its very central role in the system and for most users, and because it contains almost collective set
of the operations that are also found in the other mechanical studies. Notice however that a special tutorial, Inverse Dynamics of Muscle Systems , is devoted to topic of
musculoskeletal simulation, so we shall not go into details with this here.

The AnyBodyStudy and Studies in general


A study is really just a folder. It is a pair of braces between which you can place some specifications. Whatever you put between the braces becomes part of the study. As
every object, a study has some predefined properties that you either can set, must set, or cannot touch.

When you create a new model by means of the menus File -> New Main, the system automatically inserts an AnyBodyStudy for you (please do it and save the file under
some relevant name). It looks like this:

// The study: Operations to be performed on the model


AnyBodyStudy MyStudy = {
AnyFolder &Model = .MyModel;
Gravity = {0.0, -9.81, 0.0};
};

It contains all the things you formally need. Let's start with the last line

Gravity = {0.0, -9.81, 0.0};

The line assigns a value to the variable ‘Gravity’, which is a specification of the vector of gravitational acceleration affecting the model. The variable has no type
definitions in front of it since it is a predefined property of the AnyBodyStudy object. The system assumes that you want to work with the y axis being vertical in space. If
you prefer otherwise, simply change the direction of Gravity to reflect your choice. Please go ahead and load the model if you have not already done it by pressing F7 or
the icon.

An AnyBodyStudy has many more predefined properties that you can play with. You can get an overview of these using the Mode Tree View, which is attached to the left
of the Main Frame and to all AnyScript Editor window under the Model tab. Double-clicking any object in the Model Tree will show you properties of the objects in the
Object Description dialog box. You can also use the Model Browser to get an overview of the parameters of the studies. The Model Browser is opened from the menu

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 54 of 229

Windows -> Model Browser, whereafter you can find the study in the Model Tree which is attached to the left of this window too.

Most of the properties deal with solution methods, tolerances, and other stuff that is necessary or handy for advanced users. For a description of each property, please refer
to the AnyScript Reference manual. A few of the properties, however, are necessary to know even for casual users and they are common for all mechanical studies:

This is the time at which the study begins. In almost every case, this would be zero. Using a non-zero value of tStart is sometimes used to restrict the study to a
tStart
subset of the time is was originally developed for or if the model is driven by measured data which does not begin at t = 0.
Ah, you guessed it already. This is the time at which the study ends. Contrary to tStart, this often has to be set by the user. The standard value is tEnd = 1.0, and if
you want your study to span any more or less time, you have to set tEnd manually. A very common modeling mistake is to define data-based drivers such as the
tEnd
AnyKinEqInterPolDriver with a time span exceeding the interval from 0 to 1 and then wondering why only a small part of the movement interval gets simulated.
In this case, the user must manually specify tEnd to correspond with the end of the driver time span.
AnyBody analyzes movement in discrete time steps, and nStep specifies how many steps the system should use to come from tStart to tEnd. The steps are
equidistant, and since tStart is always the first analysis time, and tEnd the last, the interval gets divided into nStep-1 equal intervals. The default value is
nStep
nStep=100, which for most purposes is a very fine resolution. If you have a large and time-consuming model, it might be a good idea to manually set nStep to a
smaller number.

The first line of the study reads

AnyFolder &Model = .MyModel;

Notice that the first word of that line is a type definition: "AnyFolder". The predefined properties we have just discussed need no type definition because the study already
knows them. They are already defined and merely get new values by the assignments we may specify. So the type definition at the beginning of this line indicates that this
property is an addition to the study; something that was not known already. This is an important point to understand about studies: You can add almost anything to a study
and the study does not need to know its type in advance.

The significance of adding something to a study is that whatever you add becomes a part of what the study executes. This particular line defines a variable called "Model"
and sets it equal to .MyModel. If you look at the beginning of the AnyScript file, you will see that MyModel is really the folder containing the entire model the system has
generated for you (we refer to it as .MyModel with a leading dot because it is one brace up compared to where it is referenced from). This means that the entire model
comes under influence of the study. Instead of this line, we could simply have pasted the entire contents of the braces defining the MyModel in at this place, and in some
sense, this is precisely what we have done. The ampersand '&' in front of "Model" means that Model does not get replicated inside the study. Instead, the '&' means that the
study merely contains a pointer to MyModel. The concept of pointers should be very familiar to you if you have any experience in C, C++, or Java programming. If not,
simply think of a pointer as a handle to something that's defined elsewhere. Whenever you access it, you are actually handling what it is pointing to.

Instead of including the entire model, we could have chosen to point to some of the sub folders of MyModel. This would mean that the study would work on just a subset
of the model, and it can be very relevant in some cases. For instance, as mentioned earlier, you may want to compare to almost identical models; in this case you can collect
all common parts in one folder and the distinctive parts in each separate folder and two studies can easily be made with references to the common part and their respective
distinctive part. Special studies that are used to initialize properties in the model, is also a case where it is indeed useful to be able to point to parts of the model. Muscle
property calibration is such as case, which we shall look at in a special lesson of the Inverse Dynamics of Muscle Systems tutorial.

The elements of a study


When you define an AnyBodyStudy, regardless of what you include between the braces of the study, the result is three standard operations that appear in the study tree.
They each represent something you can do to the model elements the study is pointing at:

 Operation InitialConditions reads the values of whatever drivers you have included in the study and puts the model in the position of these drivers at time tStart.
This is done in a multi-step process: The model is initialized into the initial positions from load time, and the kinematics is subsequently solved in a few steps. This is
particularly useful for inspection of the specified initial positions when having problems with the initial configuration of the mechanism.
 Operatin Kinematics . A kinematic analysis is a simulation of the movement of the model without calculation of any sort of forces. This means that you can run
Kinematics as soon as you have the movement defined uniquely. You don't need any muscles in the model for this one.
 Operations InverseDynamics . This is a simulation of the forces involved in the given movement or posture and whatever can be derived from them. The
InverseDynamics operation uses the Kinematics operation as a subroutine, so this requires a correctly defined movement or posture as well as the muscles or motors
necessary to drive the model.

Each of these operations, when executed, assembles the output they generate in the Output section under the study's tree.

Running operations
You execute operations through the wide, narrow control pane that's usually located at the bottom of the screen. This is usually referred to as the Operation Window.

The lower portion of this pane is just the message window where the system writes various messages and dumps object properties when you double-click them as we did
before with the entire study. The left of the upper fields is a filtered version of the tree you can find on the left side of just about any window in the AnyBody Modeling
System. Rather than presenting all the objects of the model, this tree only comprises the studies. If you expand a study, you will find its operations, which typically are:
InitialConditions, Kinematics, and InverseDynamics.

You pick an operation by clicking it once. This highlights its name, and you can now execute it with the Run or Step buttons in the right hand field. The "Run" button starts
the study and it will run until it comes to its end or encounters an error. Once you press the run button, it changes its name to "Break", and pressing it in that state breaks the
current analysis process.

The "Step" button takes one step at a time. What a step is exactly depends a little on the type of operation. For Kinematics and InverseDynamics a step is one time step of

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 55 of 229

the movement. For InitialConditions, a step is one of the several distinct operations necessary to put the model into its initial state. We shall return to that subject in the next
lesson.

The "Reset" button returns the model to its initial state after it has gone through a sequence of time steps. You must press "Reset" before you can rerun the model.

In the following lessons we shall look in more detail at the different functionality in an AnyBodyStudy.

 Lesson 1: Mechanical System Information


 Lesson 2: Initial Conditions
 Lesson 3: Kinematics
 Lesson 4: Inverse Dynamics

We need a model with a bit more substance than the template we created above. If you do not already have our trusted arm model stored somewhere, please download it
here , save it to your disk, and load it into AnyBody. We are then ready to proceed to Lesson1: Mechanical System Information .

Lesson1: Mechanical System Information


In this lesson we are presuming that you have the arm2d.any file loaded into AnyBody. If you do not have the model on file, please download and save a copy from this
link: arm2d.any . It should look like this when you have loaded the model, run InitialConditions operation, and opened a Model View:

The mechanics of this model is fairly simple in the sense that it only has two segments and two revolute joints. However, in more realistic models with dozens of segments
connected by many joints of different types it can be very difficult to maintain the overview of the model. Making a model move requires a balance between the number of
kinematic degrees of freedom and the number of constraints, and it can be difficult to get it completely right.

This is where the systematic model information becomes important. Mechanical studies are equipped with a mechanical system description. This is included in the study’s
Objects Description, which is found by double-clicking the objects in any Model Tree View. Double-click the ArmModel study folder in the loaded model and you will
find a System description like this:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 56 of 229

The Mechanical System Information is comprised of four sections: 0) Contents, 1) List of segments, 2) List of joints and kinematic constraints, and 3) List of reaction
forces.

In a simple model like arm2d where all the segments are defined next to each other, it might seem a little unnecessary to list all the segments, but larger models typically
have the segment definitions divided over many different folders and files, and it can be helpful to see a compiled list of all of them.

AnyBody models are always defined in three dimensions and a rigid segment in three dimensional space has six degrees of freedom, i.e., three spatial movements and three
rotations. Thus, the Mechanical System Information multiplies the number of segments by 6 and reports the total number of rigid-body degrees of freedom, in this case 2 x
6 = 12. To enable the system to figure out where everything is in space we must provide 12 constraints. This is what section 2) in the Mechanical System Information is
useful for. This section counts the kinematic constraints. The sum of constraints must add up to the number of degrees of freedom in the model, i.e., 12. You can see in the
last line of the section that this indeed the case. Further up we can see how the 12 constraints come about. 2 x 5 = 10 of them come from the two revolute joints in the
model for the shoulder and elbow. A revolute joint leaves only one degree of freedom between the two reference frames it connects, so it has five constraints. With two of
these we have two degrees of freedom left in the model because 12 - 2 x 5 = 2. These remaining degrees of freedom after the joints have been added are also called the joint
coordinates. The remaining part of the section must specify this number of additional constraints.

The usual way of providing constraints for the joint degrees of freedom is by means of drivers. In our case we have simply added two drivers directly to the two joints as
the list shows. However, it does not have to be like that. We have to provide as many constraints as we have joint coordinates but the constraints need no address the joint
coordinates directly. For instance, we could also have driven the x and y coordinates of a point on the forearm.

There is also a section called "Other". This is for constraints that are neither any of the predefined joint types nor driver functions. Such constraints are very frequent in
more complex models because the AnyScript language allows for user-defined joints and other constraints to mimic complex behaviors movement patterns between
different joints. This, however, is an advanced topic that we shall postpone for now.

The final section 3) lists the reaction forces. The fact that the reaction and driver forces add up to the same number as the joints and kinemaic constraints is no coincidence.
In a straightforward model like this one, joints usually provide the same number of reactions as kinematic constraints. This is also how it is in real life in most cases,
because the mechanical joints we have in our surroundings enforce their kinematic constraints by reaction forces. But it is not always like that in the body. A knee, for
instance, can roughly be approximated as a hinge joint (many physiologists will dis a gree here) but the internal load-carrying mechanisms in the knee are not like they are
in a mechanical hinge. Instead knee reactions are provided by a complicated interplay between unilateral joint surfaces, ligaments, and muscles. So AnyBody allows for the
definition of joints that only provide kinematic constraints but not the associated reaction forces. In fact, the system also allows the opposite: Reaction forces without
kinematic constraints. For an in-depth discussion of some of these issues, please refer to the tutorial on mechanical elements . For now, the bottom line is that counting
reactions can sometimes be tricky, and the Mechanical System Information in Object Description is helpful in this respect.

A few special cases are:

1. The number of reaction and driver forces is less than the number of rigid body degrees of freedom in the model as it is the case here. This leaves some reactions to be
provided by other elements, and these elements are usually the muscles in the model.
2. If the number of reaction and driver forces is equal to the number of rigid body degrees of freedom, then the model is (usually) capable of balancing itself, and there
is no use for muscles. In fact, if you add muscles to such a mechanism, the muscles will end up doing nothing.
3. If the model has more reaction and driver forces than rigid body degrees of freedom then it is statically indeterminate. This usually means that there is something

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 57 of 229

wrong with the model. Mechanically it is equivalent to the model having multiple different w ay s of balancing itself and having no way of determining which is the
correct one the correct one is . Even though AnyBody is capable of computing the forces in such a model you will often find the solutions oscillating between the
infinitely many possibilities between time steps. Models like these should in general be avoided.

Let us investigate what happens if we make some changes in the model. Let us initially remove one of the drivers in the model leaving it kinematically indeterminate:

AnyFolder Drivers = {

//---------------------------------
// AnyKinEqSimpleDriver ShoulderMotion = {
// AnyRevoluteJoint &Jnt = ..Jnts.Shoulder;
// DriverPos = {-100*pi/180};
// DriverVel = {30*pi/180};
// Reaction.Type = {Off};
// }; // Shoulder driver

//---------------------------------
AnyKinEqSimpleDriver ElbowMotion = {
AnyRevoluteJoint &Jnt = ..Jnts.Elbow;
DriverPos = {90*pi/180};
DriverVel = {45*pi/180};
Reaction.Type = {Off};
}; // Elbow driver
}; // Driver folder

When you load the model again you will see the message:

Model Warning: Study 'Main.ArmStudy' contains too few kinematic constraints to be kinematically determinate.

When you load the model, the system automatically discovers that there seems to be less kinematic constraints than required. In this situation it might not be possible to
assemble the mechanism and it is almost certainly not possible to run a kinematic analysis. Opening the Object Description window, by double-clicking the ArmStudy
folder, produces this output:

The Mechanical System Information allows you to investigate in detail how many constraints are missing and which ones they may be. Let us shift the missing driver back
in:

//---------------------------------
AnyKinEqSimpleDriver ShoulderMotion = {
AnyRevoluteJoint &Jnt = ..Jnts.Shoulder;
DriverPos = {-100*pi/180};
DriverVel = {30*pi/180};
Reaction.Type = {Off};
}; // Shoulder driver

//---------------------------------
AnyKinEqSimpleDriver ElbowMotion = {
AnyRevoluteJoint &Jnt = ..Jnts.Elbow;
DriverPos = {90*pi/180};
DriverVel = {45*pi/180};
Reaction.Type = {Off};
}; // Elbow driver

... and try something else:

//---------------------------------
AnyKinEqSimpleDriver ShoulderMotion = {
AnyRevoluteJoint &Jnt = ..Jnts.Shoulder;
DriverPos = {-100*pi/180};
DriverVel = {30*pi/180};
Reaction.Type = {On};
}; // Shoulder driver

//---------------------------------
AnyKinEqSimpleDriver ElbowMotion = {
AnyRevoluteJoint &Jnt = ..Jnts.Elbow;
DriverPos = {90*pi/180};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 58 of 229

DriverVel = {45*pi/180};
Reaction.Type = {On};
}; // Elbow driver

What we have done here is to switch the reaction forces in the two joint drivers on. This is equivalent to imbedding motors into the joints, and it means that the system will
obtain enough reaction forces to carry the loads without help from any muscles, corresponding to the statically determinate situation 2 listed above. Loading the model does
not bring about any warnings, but if you run the InverseDynamics operation you will get the following message for each time-step:

'ArmStudy': The muscles in the model are not loaded due to kinetically over-constrained mechanical system.

And the Object Description window will give the following feedback:

- indicating that the model is precisely statically determinate with 12 reactions corresponding to the 12 rigid body degrees of freedom.

Having familiarized ourselves with the Mechanical System Information in the Object Description of the study, let us proceed to Initial Conditions in the next lesson .

Lesson2: Initial Conditions


Before we look at the InitialConditions operation, let us just notice that when the model is loaded, the segments of the model are positioned in space according to their
definition in terms of the r0 and Axes0 properties in each segment's definition. These are called the load-time positions.

In the figure below, the user has tried to position the forearm and the upper arm approximately at the right positions and angles at load time. This is always a good idea, but
it is almost impossible to get them completely in place, and it is not necessary. Indeed, in more complicated models, you can often find the segments and muscles in a big
mess at load time. Typically, you will want to see what the model looks like when it has been assembled correctly for time step 1. This is what the InitialConditions
operation is for.

The load-time positions of segments in a simple arm model. Notice that the forearm and upper arm do not meet correctly at the elbow joint.

When you run the InitialConditions operation, it will attempt to put the model in the position is has at time = tStart. This may or may not be possible, and in the
development stages of a model, when the joints and drivers are not yet fully defined, it is definitely not possible, and this is the reason why the system does not do it
automatically when you load the model. Running the InitialConditions operation produces a correctly assembled arm:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 59 of 229

The arm correctly assembled at the elbow by SetInitialConditions.

Here's a more detailed explanation: The system must perform a kinematical analysis to connect the model correctly at the joints. This requires that the model is
kinematically determinate. Another way of expressing that is that there must be the correct number of - and relationship between joints and drivers in the model. It usually
takes some iterations in the model development to get it right. During these iterations it is useful to be able to load the model and see a picture of it, and this is why the
loading simply positions the segments where the user placed them.

Instead of simply running the InitialConditions operation, you can also single-step through it to see what it does. This is done by clicking the "Step" button instead of the
"Run" button.

Picking the step button.

The first step re-establishes the load-time conditions. This means that it positions the modes as it was when you loaded it. This is useful for identification of kinematic
problems. The second step positions the segments honoring the joints. The third does not seem to do much, but it is used for positioning muscles wrapping over surfaces. It
is just not visible in this simple model.

The InitialConditions study can be thought of as the first step of a kinematic analysis, which will be the subject of the next lesson.

Lesson 3: Kinematic Analysis


The Kinematics operation has a short and a very long explanation. The short explanation is that it makes the model perform whichever movement you have imposed on it
by the drivers you have defined in the model. And it only does the movement. There is no calculation of forces involved, and the system does not even have to be properly
balanced to be subjected to the Kinematics operation. However, it does have to be kinematically determinate, but that concept is definitely a part of the longer explanation.

So, brace yourself, and let's venture on to...

The long explanation


An AnyBody model is really a collection of rigid segments. You can think of them as a bunch of potatoes floating around in space. Technically, each potato is called a
"rigid body", but the term "body" can be misinterpreted in the context of a body modeling system like AnyBody, so we call them "segments".

When a segment flows around in space, it can move in six different directions. We call them degrees of freedom and usually think of them as movement along the three
coordinate axes and rotation about the same axes. We call these movement directions "degrees of freedom" and an unconstrained segment in space has six degrees of
freedom. If we have n segments in the model, the model will have a total of 6n degrees of freedom unless some of them are constrained somehow. The purpose of the
kinematic analysis is to determine the position of all the segments at all times, and this requires 6n pieces of information about the positions to resolve the 6n degrees of
freedom. The pieces of information are mathematically speaking equations. So kinematic analysis is about solving 6n equations with 6n unknowns.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 60 of 229

A usual way of constraining degrees of freedom (or adding equations to the system) is to add joints to the model. When you join two segments they lose some of their
freedom to move independently. They become constrained to each other. Consider two segments joined at their ends by a ball-and-socket joint. They are now under the
constraints that the x, y and z coordinates of the joined points must be the same. In other words, a ball-and-socket joint adds three constraints or three equations to the
system.

If you add enough joints to the system to provide all 6n constraints, then it might be mathematically possible to solve the equations and find the position of all the
segments. But the result would not be very exciting because the system would not be able to move. Usually a body model will have enough joints to keep the segments
together but few enough to let the model move. After all, movement is what most higher organisms do. So where do the remaining constraints or equations come from?
They are the drivers. When the joints have eaten up their part of the degrees-of-freedom, enough drivers must be added to resolve the remaining unknowns in the system up
to the required number of 6n. When the AnyBody Modeling System performs the Kinematics operation, these drivers are taken through their sequences of values, and the
positions of all the segments are resolved for each time step by solving the 6n equations.

When the model is set up in such a way that it has 6n equations and these equations can be solved, then it is said to be kinematically determinate. Usually this is necessary
to perform the kinematic analysis. We say "usually" because there are a few exceptions where the system can be solved even when the number of equations is different
from 6n. There are also some cases where the system cannot be solved even though there are 6n equations available. Both cases are connected with redundant constraints.

If you define two or more constraints that in some way constrain exactly the same degrees of freedom in the same way, then they are redundant. For instance, you might by
mistake repeat the definition of a joint. You will then have two joints that work exactly the same, and the equations provided by those two joints will be redundant. You
will see them when you count constraints, but they will not have much effect.

The AnyBody Modeling System can sometimes cope with models that have too many constraints as long as those constraints are not conflicting, i.e., some of them are
redundant. But it is a good rule to make sure that you have the same number of degrees-of-freedom and constraints.

If you have too many constraints and they are incompatible, then the system is kinematically over-determinate. If you have too few constraints, or some of the constraints
are redundant, then the system may be kinematically indeterminate. Both cases are likely to prevent the Kinematics operation to complete.

Actually, even when you have a kinematically indeterminate system, the Kinematics operation can fail. This is actually very easy to picture. Sometimes the segments of the
model may be configured such that they cannot reach each other, or in such a way that they interlock. The real world is full of that sort of mechanisms: Car doors that get
stuck or refuse to close, locks that will not unlock, or stacked glasses that wedge inseparably into each other. Computer systems that model the real world will have them
too, and just like the real world it can sometimes be difficult to find out what the problem is.

Running kinematic analysis


Now that you know the basics of kinematic analysis, let us look at how it is performed. We need an example to work on, and this one will serve the purpose:
demo.SliderCrank3D.any

When you load it and open a Model View you will see that this is a very simple mechanism comprising only three segments. They are not yet connected correctly at their
joints, but they will be if you run the Kinematics operation. Go to the Study tree, pick Kinematics and click the run button. You will see the model assemble and start
moving.

The Kinematics operation is precisely an analysis. It assembles data when it runs, and you can subsequently investigate those results in the ChartFX view. Pick Window ->
ChartFX (new) to open it. The kind of results you can get from the Kinematics study is everything that has to do with positions, velocities, and accelerations. You may
expand the tree until you reach the Slider segment, and you can chart its acceleration by choosing the rDDot property.

Notice the naming of the positional properties: r is position, rDot is velocity, and rDDot is acceleration. "Dot" or "DDot" are reflections of the mathematical custom of
designating differentiation with respect to time by a dot over the symbol. So velocity would be 'r' with a dot over, and acceleration would be 'r' with two dots. Try browsing

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 61 of 229

around the tree and look up the various available data.

You may encounter some strange looking results like this one:

Why would anything in a smoothly running model behave like this? The answer lies in the ordinate axis. You will notice that it has no values on it, and if you hold the
mouse over a point on the curve a small window will pop up and show you the value:

You can see that the value is 4.45e-14. For all practical purposes this is zero, and this is also why there are no values on the ordinate axis. What you see here is really zero
augmented by numerical round-off errors.

Final remarks
Notice that kinematic analysis determines velocities and accelerations in addition to positions. The position analysis is by far the more challenging because the equations
are nonlinear, whereas solution for velocity and acceleration involves linear equations once the positions have been determined. Please notice also that due to the very
general approach used by the AnyBody Modeling System, it handles closed kinematic chains. This is crucial in biomechanics where closed chains occur very frequently,
for instance in bicycling, gait, and whenever the model grabs something with both hands.

Although the kinematic analysis is useful in its own right for lots of purposes, it is also the first step of the InverseDynamics operation, the subject of the next lesson .

Lesson 4: Inverse Dynamics


The inverse dynamic analysis in AnyBodyStudy is at the heart of what the AnyBody Modeling System does. An InverseDynamics operation is like the Kinematics
operation, except it is augmented with calculation of forces in the system, i.e. kinetic or dynamic analysis.

Computing forces in a rigid body mechanical system is more difficult than it may seem. In principle, resolving forces is a question of setting up the equilibrium equations
and solving them. But in mechanism analysis in general and biomechanics in particular, there are several complications. The system may very easily become statically
indeterminate, which means that there are not enough equilibrium equations available to resolve the forces in the system. Another complication is caused by the muscles in
the system because they can only pull. This constrains the space of possible solutions and adds a fair bit of mathematical complexity to the problem.

In AnyBodyStudy, these complexities are handled with algorithms that assume that the mechanical system is a musculoskeletal system. The inverse dynamic solver
basically deals with

 The statical indeterminacy of the musculoskeletal system


 Unilateral forces elements.

The class called AnyMechStudy does also contain an InverseDynamics operation. This operations is far more simple and does not deal with either of these problems. It
simply solves the very basic inverse dynamics problem of a general simple mechanical system, namely to solve the dynamic equilibrium equations for a equal amount of
unknown forces, the so-called reaction forces.

To conclude this tutorial, please try InverseDynamics operations in the arm model, arm2d.any , and the slider crank mechanism, demo.SliderCrank3D.any . In both case,
you will now see forces being calculated, i.e. forces that a non-zero in the output. But please also notice how the slider crank study is defined with simpler AnyMechStudy
whereas the arm model uses AnyBodyStudy.

If you use AnyMechStudy in the arm model, the analysis will stop with a failure, because it cannot balance the mechanism. This is because the AnyMechStudy does not
recognize the muscles as unknown forces. It regards them as applied (known) forces (which will be zero because their value is not defined anywhere) and therefore there
are no forces to balance the moments exerted about the elbow and should joints by the external load.

Much more details about inverse dynamics of musculoskeletal systems are found the special tutorial on the topic .

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 62 of 229

Making things move


Most biomechanical investigations involve some sort of movement, so getting the model to move in the desired way is at the core of musculoskeletal modeling. The
AnyBody Modeling System offers many and rather advanced methods to make this happen. This tutorial explains the basics and some of the more common approaches.

The figure above is actually a sequence of superimposed images illustrating a movement. In the AnyBody Model View window, this will of course be an animation. The
point of the figure, however, is that the movement is derived from a combination of joint articulations, and this introduces the concept of degrees-of-freedom, which we
shall abbreviate in the following as DoF.

The number of DoFs in a model can be thought of as the number of different articulations the model has. The knee, for instance, is a hinge joint and can only flex or extend
with respect to its predefined rotation axis, so this joint provides one DoF to the model. The hip joint, on the other hand, is a spherical joint, so it has three different
rotations and therefore provides three DoFs to the model. Anatomically, these three DoFs might be called flexion/extension, abduction/adduction and internal/external
rotation, but this is just one possible choice of terminology related to a selected coordinate system. We could choose infinitely many other angle definitions and sequences
in the hip. Regardless of the choice there would always only be three independent possibilities, so the concept of DoF is rather general, and we shall explore it in a little
more detail in the following on a very simple model.

Please download and save the file pendulum.any in a working directory. Load the model into AnyBody and open a new model view. You should see a vertical segment
with a point at each end. It is, in fact, a pendulum model linked to the global reference frame by a revolute joint at its upper end point. We use this example because it is
very simple and has a remote similarity with a human limb.

A hinged pendulum, like a forearm hinged at the elbow, will have just one DoF. If you unfold the list of operations under MyStudy in the Operation window on the left
side of the screen, you can select Kinematics and click the run-button as shown below:

Instead of a moving pendulum you are rewarded with an error message:

Model is kinematically indeterminate : Position analysis failed : 6 independent constraints and 7 unknowns

The message means that there is one equation missing in the system to define the position of the pendulum. This comes down to the fact that the pendulum has one DoF,
i.e. one movement opportunity, and the model does not specify how to move that one DoF. The system has no way of determining which movement to perform before we
have specified it.

In the following lessons we will look at simple and more advanced ways to drive a model. For simplicity, we’ll stick with the simple pendulum, but exactly the same
principles apply to much more complex models.

Let’s initially review simple drivers in Lesson 1 .

Lesson1: Simple drivers

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 63 of 229

As mentioned above, we often have preconceived ideas about a system’s natural DoFs, such as abduction of the shoulder or flexion of the knee. In the case of the
pendulum, we might get the idea that the natural DoF is its rotational angle away from its resting vertical position. And we can very easily drive the pendulum using this
DoF.

The simplest mechanism of motion drivers in AnyBody is called AnyKinMotion. With Pendulum.any open in an editor and the model loaded, please place the cursor in the
editor window just below then ending brace of the AnySeg Pendulum definition. Then click the Classes tab on the left hand side of the editor window. Unfold the class list
and scroll down to find AnyKinMotion. Right-click and insert an instance at the cursor position:

AnySeg Pendulum = {
Mass = 1;
Jii = {1, 0.01, 1}/10;
AnyRefNode Origin = {
sRel = {0, 0.5, 0};
};
AnyRefNode P1 = {
sRel = {0, -0.5, 0};
};
AnyDrawSeg drw = {};
};
AnyKinMotion <ObjectName> =
{
//MeasureOrganizer = ;
//CType = ;
//AnyKinMeasure &<Insert name0> = <Insert object reference (or full object definition)>; You can make any number of these objects!
AnyParamFun &<Insert name0> = <Insert object reference (or full object definition)>;
};

The prototype of the AnyKinMotion class is set up to allow several different options. But the simplest of these is to directly specify something to drive and a function to
drive it with. So we start out by giving the object a name and removing all of its content.

AnyKinMotion JointDriver = {
};

Then we specify what to drive by making reference to the pendulum joint:

AnyKinMotion JointDriver = {
AnyRevoluteJoint &Jnt = .Joint;
};

Now we have specified what to drive, so all that’s left is to create a function to drive it with. AnyBody contains a number of predefined function types that you can find in
the Classes Tree, for instance AnyFunPolynomial. As the name indicates, this is a polynomial function and it can have any number of coefficients. A common use is to
drive motion either in a very standardized way, for instance with constant velocity or constant acceleration, or to drive a motion by data to which a polynomial has been
fitted.

Try inserting the red part of the code below:

AnyKinMotion JointDriver = {
AnyRevoluteJoint &Jnt = .Joint;
AnyFunPolynomial DriverFun = {
PolyCoef = {{0, 3, 5}};
};
};

In the matrix PolyCoef, each row contains the coefficients for a time function driving one degree of freedom. The revolute joint we are driving only has one degree of
freedom, so the matrix only has one row, but it still has to be defined as a matrix rather than a vector, i.e. with double braces at each end. The polynomial coefficients then
come in increasing order and define the following driver function:

Joint angle = 0 + 3 t + 5 t ^2 [rad]

To get higher polynomial orders, simply add more terms to the vector.

Now try loading the model. If you have followed the instructions, you should no longer get the warning that that model is kinematically indeterminate. It now has the same
number of drivers as degrees of freedom, and we can expand the MyStudy branch in the Operation tree on the left hand side of the main frame, select kinematics and click
“Run”. If you have a model view open, you should see the pendulum starting to move and accelerate as it rotates a little more than one round before the end of the analysis
at t = 1 second.

The use of AnyKinMotion objects to drive a model is in principle always like this, but you can select any Kinematic Measure to drive, i.e. not just a simple joint angle, and
you can use any function derived from the abstract AnyParamFun class to drive it with.

In lesson 2 we shall see how this same mechanism allows you to drive the pendulum by motion capture data.

Lesson 2: Using motion capture data


In biomechanics, we often want to make our models move as we have measured in the laboratory and the measurement technique would often be tracking of optical
markers in space by means of synchronized cameras. There are many such systems available commercially, but a common feature of most of the systems is that they are
capable of saving data on a standard format called a C3D file. Such a file contains data of the spatial trajectory of optical markers fixed to the object whose motion we want
to record. The C3D file can also contain analog data such as force platform measurements or EMG. To make things easy, AnyBody can read the data from a C3D file
directly. Please download and save the file pendulum.c3d in the directory where you saved the Pendulum.any file.

Then place the cursor in the editor window just before the AnyKinMotion object, click the Classes tab, unfold the class list, and locate the AnyInputC3D class. Right-click
the class and choose “Insert Class Template”.

AnyInputC3D <ObjectName> =
{
FileName = "";
//ReadAllDataOnOff = On;
//TruncateExtraCharsInNamesOnOff = On;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 64 of 229

//PointsScaleFactor = 1;
//ConstructModelOnOff = On;
//MarkerUseAllPointsOnOff = Off;
//MarkerUseCamMaskOnOff = On;
//MarkerIndices = ;
//MarkerLabels = ;
//MarkerFilterIndex = 0;
//ProcessedDataFilterIndex = 0;
//AnalogFilterIndex = -1;
/*Filter =
{
z0 = ;
AutomaticInitialConditionOnOff = On;
FilterForwardBackwardOnOff = On;
N = 2;
W = ;
Fs = 0;
Fc = {10};
Type = LowPass;
};*/
//WriteMarkerDataToFilesOnOff = Off;
//MarkerScaleXYZ = {0.025, 0.025, 0.025};
//MarkerRGB = {0.65, 0.65, 0.65};
//MarkerDrawOnOff = On;
//MarkerInterPolType = Bspline;
//MarkerBsplineOrder = 8;
};

As you can see, the class has a lot of settings, but for now we shall only use two of them, namely FileName and ConstructChartOnOff. We also give a name to the object:

AnyInputC3D C3D = {
FileName = "pendulum.c3d";
//TruncateExtraCharsInNamesOnOff = On;
//MakeNameUniqueStr = "_";
//PointsScaleFactor = 1;
//ConstructModelOnOff = On;
ConstructChartOnOff = Off;

ConstructChartOnOff instructs the C3D object to not draw 3D trajectories.

Now, try loading the model again. You may get the following error message:

Time, 't', has an invalid value for this interpolation

C3D files contain marker trajectories covering a certain time span and what goes on outside that interval is undefined. Furthermore, the very beginning and very end of that
time span may not be useful for the motion interpolation due to initial transients. If you have a C3D file of unknown duration, then you somehow have to figure out its start
and end times to enable AnyBody to analyze it. A simple way to do this is to allow AnyBody to load the file by temporarily disabling the study section of your model. This
will eliminate the study’s conflicting start and end times. Just block-select the study section and click the “Comment out” tool button over the editor window:

// The study: Operations to be performed on the model


// AnyBodyStudy MyStudy = {
// AnyFolder &Model = .MyModel;
// Gravity = {0.0, -9.81, 0.0};
// };

Now the model should load with no problems, and you can go to the tree view in the left hand side of the screen, click the Model tab and unfold the MyModel tree down to
the C3D object as shown below.

A bit down in this object you find the Header section. When you unfold it you get access to a number of basic properties of the C3D file. Each time you double-click a
property, a window will pop up and give you its value. The important properties in question are these:

FirstFrameNo = 1

LastFrameNo = 1000

VideoFrameRate = 100

This shows that the file has a total of 1000 frames at 100 frames/sec, i.e. the simulation time spans ten seconds. We can now go to the editor window and remove the
temporary double slashes in front of each line in the study section.

// The study: Operations to be performed on the model


AnyBodyStudy MyStudy = {
AnyFolder &Model = .MyModel;
Gravity = {0.0, -9.81, 0.0};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 65 of 229

};

…and insert specifications of simulation time:

AnyBodyStudy MyStudy = {
AnyFolder &Model = .MyModel;
Gravity = {0.0, -9.81, 0.0};
tStart = 0.05;
tEnd = 9.95;
};

There is also an automated way to handle the problem. The frame rate variables we have just processed manually can also be referred to directly in the study section, such
that the tStart and tEnd parameters automatically adapt to the C3D file. Try this instead:

AnyBodyStudy MyStudy = {
AnyFolder &Model = .MyModel;
Gravity = {0.0, -9.81, 0.0};
AnyIntVar FirstFrame = Main.MyModel.C3D.Header.FirstFrameNo;
AnyIntVar LastFrame = Main.MyModel.C3D.Header.LastFrameNo;
tStart = FirstFrame/Main.MyModel.C3D.Header.VideoFrameRate+2*Kinematics.ApproxVelAccPerturb;
tEnd = LastFrame/Main.MyModel.C3D.Header.VideoFrameRate-2*Kinematics.ApproxVelAccPerturb;
};

Notice that we start the simulation 2*Kinematics.ApproxVelAccPerturb after the beginning of the recorded motion and we end it similarly before the end of the recording.
The variable Kinematics.ApproxVelAccPerturb contains information about the algorithm’s necessary elbow room on each side of the analyzed interval. This eliminates
possible numerical trouble with end points.

Now the model should load and the ModelView window (open a new one if you do not have it) will display a small, grey dot to the right of the pendulum end.

The small dot is in fact the single marker contained in Pendulum.c3d. A typical file from a real motion capture experiment can contain dozens of markers, but in the
interest of simplicity we have just included a single one here. The AnyInputC3D object automatically creates the small dots and the drivers necessary to move them around
as they were recorded. If you run the Kinematics operation (Click the Operation tab in the tree view on the left hand side of the screen, select Kinematics and click run),
you will see the pendulum move as before, while the marker performs an oscillating motion back and forth (Tip: if the motion is too fast to see properly, increase the
number of time steps, nStep, in the study).

So how do we get the marker to drive the pendulum? This can be done quite easily with the AnyKinDriverMarker object. The steps are:

1. Remove the existing driver that makes the pendulum rotate.

2. Drive the marker point, P1, on the pendulum to follow the data recorded in the C3D file.

Start by selecting the existing AnyKinMotion driver and comment it out of the model. That takes care of step 1.

Then click the Classes tab on the left hand side of the editor window, insert a new AnyKinDriverMarker template, and give it a name:

AnyKinDriverMarker C3Dmotion =
{
//MeasureOrganizer = {};
//CType = ;
//WeightFun = {};
//DriverPos0 = {};
//DriverVel0 = {};
//DriverAcc0 = {};
AnyRefFrame &<Insert name0> = <Insert object reference (or full object definition)>;
//AnyRefFrame &<Insert name1> = <Insert object reference (or full object definition)>;
//AnyParamFun &<Insert name0> = <Insert object reference (or full object definition)>;
};

Just as before, the AnyKinDriverMarker object needs to know what to drive and what to drive it with. The “what to drive” part is the position of P1 on the pendulum. This
is specified with the first reference frame in the object:

AnyKinDriverMarker C3Dmotion =
{
//MeasureOrganizer = {};
//CType = ;
//WeightFun = {};
//DriverPos0 = {};
//DriverVel0 = {};
//DriverAcc0 = {};
AnyRefFrame &Marker = .Pendulum.P1;
//AnyRefFrame &<Insert name1> = <Insert object reference (or full object definition)>;
//AnyParamFun &<Insert name0> = <Insert object reference (or full object definition)>;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 66 of 229

};

The mnarker coordinates in the C3D file are recorded in the laboratory coordinate system, which we chall assume is our global reference frame. Driving from GlobalRef is
default in linear measures, so we need not mention GlobalRef explicitly in the AnyKinDriverMarker object.

We are going to drive the point directly by means of the interpolation function specifying the marker trajectory in the C3D object. First, give a reasonable name to the
AnyParamFun and remove the stuff after the equality sign:

AnyKinDriverMarker C3Dmotion =
{
//MeasureOrganizer = {};
//CType = ;
//WeightFun = {};
//DriverPos0 = {};
//DriverVel0 = {};
//DriverAcc0 = {};
AnyRefFrame &Marker = .Pendulum.P1;
//AnyRefFrame &<Insert name1> = <Insert object reference (or full object definition)>;
AnyParamFun &Trajectory = ;
};

Then click the Model tab in the tree view on the left hand side of the editor window, unfold the MyModel branch and subsequently the C3D object, Points, Markers, L000
and arrive at PosInterpol as shown below.

This is the actual interpolation function of the marker in question. Place the cursor after the equality sign of the AnyParamFun line, right-click the PosInterpol object, and
choose “Insert object name”. You should get this:

AnyKinDriverMarker C3Dmotion =
{
//MeasureOrganizer = {};
//CType = ;
//WeightFun = {};
//DriverPos0 = {};
//DriverVel0 = {};
//DriverAcc0 = {};
AnyRefFrame &Marker = .Pendulum.P1;
//AnyRefFrame &<Insert name1> = <Insert object reference (or full object definition)>;
AnyParamFun &Trajectory =
Main.MyModel.C3D.Points.Markers.L000.PosInterpol;
};

Now load the model and run the kinematic analysis. You will get the following error message:

Model is kinematically over-constrained : Position analysis failed : 2 unsolvable constraint(s) found

It is time to think back to the concept of degrees-of-freedom, DoF. In the beginning of the tutorial, we established that the free pendulum has one DoF. But the marker
trajectory has three coordinates and therefore wants to drive P1 of the pendulum in x, y and z, i.e. two DoFs more than we have available. There are two possible solutions
to this problem. Either we pick only one of the directions given by the marker and let the revolute joint decide the rest, or we have to accept that the pendulum cannot
follow the marker completely in all three DoFs, i.e. something has to give.

Driving just one direction would be fairly simple in this case, but in a more complicated model with many markers, the selection of a subset of directions to drive can be a
very tedious process. Another aspect to consider is that marker data are measured and therefore always infested with various types of errors and noise. One of the serious
errors in motion capture technology is the so-called soft tissue artifact or skin artifact. It comes from the fact that markers are placed on the skin at some distance from the
bone whose motion they are supposed to record. Between the marker and the bone are layers of skin, fat and muscle, so the marker never moves exactly with the bone. It is
therefore natural in the model to presume that the connection between the marker and the bone is not a rigid one, and when that is the case, AnyBody will accept drivers on
more DoFs than the model actually has.

Resolving the kinematics in the presence of moving markers is somewhat more complicated numerically, so we have to ask for a specific kinematics solver that can handle
it. This is done in the study section:

AnyBodyStudy MyStudy = {
AnyFolder &Model = .MyModel;
Gravity = {0.0, -9.81, 0.0};
AnyIntVar FirstFrame = Main.MyModel.C3D.Header.FirstFrameNo;
AnyIntVar LastFrame = Main.MyModel.C3D.Header.LastFrameNo;
tStart = FirstFrame/Main.MyModel.C3D.Header.VideoFrameRate+2*Kinematics.ApproxVelAccPerturb;
tEnd = LastFrame/Main.MyModel.C3D.Header.VideoFrameRate-2*Kinematics.ApproxVelAccPerturb;
InitialConditions.SolverType = KinSolOverDeterminate;
Kinematics.SolverType = KinSolOverDeterminate;
};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 67 of 229

The two additional lines select a kinematic solver for the InitialConditions and Kinematics operations that will accept more kinematic constraints than the system has DoFs.
Now you can reload and run the kinematic analysis and you should see the pendulum following the marker movement. You cannot see the marker during the movement
because it is hidden inside the pendulum. In fact, the marker is not strictly necessary for the analysis and we can get rid of it altogether by an additional specification in the
C3D object:

AnyInputC3D C3D = {
FileName = "pendulum.c3d";
//ReadAllDataOnOff = On;
//TruncateExtraCharsInNamesOnOff = On;
//PointsScaleFactor = 1;
ConstructModelOnOff = Off;
ConstructChartOnOff = Off;
//MarkerUseAllPointsOnOff = Off;
//MarkerUseCamMaskOnOff = On;
//MarkerIndices = ;
//MarkerLabels = ;
//MarkerFilterIndex = 0;
//ProcessedDataFilterIndex = 0;
//AnalogFilterIndex = -1;
/*Filter =
{
z0 = ;
AutomaticInitialConditionOnOff = On;
FilterForwardBackwardOnOff = On;
N = 2;
W = ;
Fs = 0;
Fc = {10};
Type = LowPass;
};*/
//WriteMarkerDataToFilesOnOff = Off;
//MarkerScaleXYZ = {0.025, 0.025, 0.025};
//MarkerRGB = {0.65, 0.65, 0.65};
//MarkerDrawOnOff = On;
//MarkerInterPolType = Bspline;
//MarkerBsplineOrder = 8;
};

With the unnecessary marker gone from the model, the kinematic analysis runs much faster than before. Each marker adds DoFs and constraints to the model, and they
require solution time. It is therefore more efficient to leave the markers out unless you really need them.

Now that there is driver between pendulum and the marker, it is possible to simultaneously draw both the point on the pendulum and the marker from the C3D file. To do
this, start by placing the cursor inside the AnyKinDriverMarker object.

Then click the Classes tab on the left hand side of the editor window, insert a new AnyDrawKinMeasure template, and give it a name:

AnyKinDriverMarker C3Dmotion =
{
//MeasureOrganizer = {};
//CType = ;
//WeightFun = {};
//DriverPos0 = {};
//DriverVel0 = {};
//DriverAcc0 = {};
AnyRefFrame &Marker = .Pendulum.P1;
//AnyRefFrame &<Insert name1> = <Insert object reference (or full object definition)>;
AnyParamFun &Trajectory =
Main.MyModel.C3D.Points.Markers.L000.PosInterpol;

AnyDrawKinMeasure drw =
{
//Visible = On;
//Opacity = 1;
//RGB1 = {0.8, 0.3, 0.3};
//RGB2 = {0.3, 0.8, 0.3};
//RGB3 = {0.3, 0.3, 0.8};
//RGB4 = {0.8, 0.5, 0.2};
//Label = On;
//Size = 0.02;
//Line = On;
//Text = "";
//TextSize = 30;
};
};

If you reload the model, you should see something like this:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 68 of 229

The blue dot illustrates the marker from the c3d file and the red line is drawn to illustrate the difference between the point on the segment and the measured point. Please
notice that there is a small ball hidden inside yellow sphere from the drawing of the segment. The plot also shows a label “KDM”, which indicates that it is an
AnyKinDriverMarker that is drawn.

The line between the two points and the label can be removed by changing the Label and Line settings to Off. Let us also change the size of the dots such that we can see
both the point on the segment as well as the measured point.

AnyDrawKinMeasure drw =
{
//Visible = On;
//Opacity = 1;
//RGB1 = {0.8, 0.3, 0.3};
//RGB2 = {0.3, 0.8, 0.3};
//RGB3 = {0.3, 0.3, 0.8};
//RGB4 = {0.8, 0.5, 0.2};
Label = Off;
Size = 0.07;
Line = Off;
//Text = "";
//TextSize = 30;
};

Reloading the model should show you something like this:

Let us briefly investigate the kinematic constraints of our model. Click the Model tab in the tree view on the left hand side of the screen and unfold the Joint branch. Inside
you find Constraints, and after unfolding that branch you find the property CType. If you double-click it, the popup window shows the following:

CType = {Hard, Hard, Hard, Hard, Hard}

CType appears to be a vector with five components, owing to the fact that a revolute joint has five constraints, and CType specifies that all of these are Hard. This means
that the kinematic solver is not allowed to violate any of them.

If you similarly locate and unfold the C3DMotion object you again find a CType, and double-clicking it reveals

CType = {Soft, Soft, Soft}

We have implicitly specified that the joint is a hard constraint while the marker is a soft constraint. Joints automatically have their constraint types set to Hard and
AnyKinDriverMarker objects automatically have soft constraints, but these rules can be overridden by the user by explicit specification of CType in the respective objects.

In Lesson 3 we investigate how to filter noise out of the measured data.

Lesson3: Noise and filters


Let us run the Kinematics operation and investigate the results. After the operation has completed, please click Window -> CharFX 2D (New) and plot the position vector
of the pendulum as shown below:

The red, green and blue curves designate x, y and z locations respectively of the center of mass of the pendulum. We see the expected sinusoidal curves for x and y and a z
location that is constantly zero. It all looks fine and dandy, but closer investigation will reveal that it is not.

If we plot the velocity, rDot, rather than the position, we begin to see the problem:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 69 of 229

It is obvious that the motion is not as smooth as we would expect from the first set of graphs, and it gets even worse if we plot the accelerations, rDDot:

Since forces in a mechanical system stem from accelerations, an analysis of the force in this system would lead to a completely different result than we would expect. The
problem is due to noise in the measurements, and noise is always present in several different forms. Although it can be minimized by careful experimental procedures and
good equipment, it can never be completely removed. Therefore, it is always necessary to filter motion capture data before use.

The AnyInputC3D class has a default filter built in. It is a special case of a more general filter class in AnyBody, and the special case is a second-order, zero-phase
Butterworth filter with a cutoff frequency of 10 Hz. If you do not specify anything else, then this is what you are going to get. In this case, it is obviously not sufficient, so
let’s play a bit with the settings and see whether we can get better results.

The filter section of the AnyInputC3D section is currently inactive. Please remove the /* */ surrounding the object, and you will have the following:

Filter = {
z0 = ;
AutomaticInitialConditionOnOff = On;
FilterForwardBackwardOnOff = On;
N = 2;
W = ;
Fs = 0;
Fc = {10};
Type = LowPass;
};

The first two lines pertain to the filter’s initial condition, and z0 cannot be set when AutomaticInitialConditionOnOff is set to On, meaning that the initial condition of the
filter gets computed automatically. The automatic computation is an attempt to minimize initial transients in the signal, but it may not always be good enough, and in this
case it can be relevant to set the initial conditions. For now, let us keep the automatic setting and therefore remove the incomplete line with z0:

Filter = {
// z0 = ;
AutomaticInitialConditionOnOff = On;
FilterForwardBackwardOnOff = On;
N = 2;
W = ;
Fs = 0;
Fc = {10};
Type = LowPass;
};

The third line, FilterForwardBackwardOnOff, is mostly included for the sake of completeness. When it is set to on, zero phase shift in the filter is obtained by filtering
twice, i.e. first forward and then backward in the signal, which is the standard approach. Please leave it as it is unless you really know what you are doing.

The property N is simply the order of the filter. The default value is 2 and higher values lead to sharper cuts at the specified cutoff frequency.

W is the normalized cutoff frequency. Allowed values are between zero and one with one corresponding to half of the sampling frequency. However, it is not allowed to
specify W when filtering data from a C3D file because the file already contains information about the sampling frequency, so you can safely delete this line.

Fs is the sampling frequency, and like W, we cannot specify it when reading from a C3D file, so please remove this line.

Fc is the cutoff frequency and is set to 10 Hz by default. The dilemma with filters is always that they can reduce noise and other undesirable elements of the signal, but in
the process they also may remove desirable parts of the signal or even introduce artifacts. 10 Hz is a relatively safe value for experiments with human motion, but it would
obviously not be a safe choice if we were modeling insect motion or other phenomena with higher frequency content.

Finally, the last line specifies the type of the filter as low pass, which is the relevant value for a signal like this, where the noise is high frequency, but the filters in
AnyBody also allow for other types. Please refer to the reference manual for a complete description.

In the graph of Pendulum.r above, the red curve seems to have a frequency of about 0.2 Hz and the green curve about 0.4 Hz. This is safely below our present 10 Hz cutoff
frequency, so there seems to be room to eliminate more noise by using a lower value of Fc. If we change

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 70 of 229

Filter = {
// z0 = ;
AutomaticInitialConditionOnOff = On;
FilterForwardBackwardOnOff = On;
N = 2;
Fc = {2};
Type = LowPass;
};

…we can get the following accelerations:

They look much more reasonable, but notice that each end of the curve is influenced by the initial conditions of the filter. Filters remove noise but they are also sources of
artifacts in the model and nothing is ever completely perfect.

In this and the previous lesson we used the system’s ability to handle over-constrained models to drive the pendulum with a marker that supplies three constraints even
though the pendulum only has one degree of freedom. The additional information in the redundant constraints can be used to our advantage for other purposes too, as we
shall see in Lesson 4 .

Lesson 4: Parameter identification


In this lesson we shall consider a source of uncertainty on motion capture experiments and musculoskeletal modeling in general that is completely different from the noise
of the preceding section. The issue in this section is that a musculoskeletal model contains assumptions about the model dimensions that we really cannot know in advance.
A femur, for instance, is attached to the hip joint located rather deeply inside the lower abdomen and we cannot palpate it or measure its location without advanced imaging
techniques. Thus, in a musculoskeletal model of a given individual, properties as basic as the length of the femur and the location of the hip joint center are always
somewhat uncertain. In this section, we are going to see how the data in a C3D file can help us automatically determine these parameters with good accuracy.

Please download and save the file multiple.c3d .

Then close all open windows in AnyBody and create a new Main file by clicking the ‘M’ tool button in the upper left hand corner of the main frame. This creates an empty
model into which you can insert an AnyInputC3D object, refer to the multiple.c3d file and specify the filter as we did before:

Main = {

// The actual body model goes in this folder


AnyFolder MyModel = {

// Global Reference Frame


AnyFixedRefFrame GlobalRef = {

// Todo: Add points for grounding of the model here

}; // Global reference frame

AnyInputC3D C3D = {
FileName = "multiple.c3d";
//ReadAllDataOnOff = On;
//TruncateExtraCharsInNamesOnOff = On;
//PointsScaleFactor = 1;
//ConstructModelOnOff = On;
ConstructChartOnOff = Off;
//MarkerUseAllPointsOnOff = Off;
//MarkerUseCamMaskOnOff = On;
//MarkerIndices = ;
//MarkerLabels = ;
//MarkerFilterIndex = 0;
//ProcessedDataFilterIndex = 0;
//AnalogFilterIndex = -1;
Filter = {
AutomaticInitialConditionOnOff = On;
FilterForwardBackwardOnOff = On;
N = 2;
Fc = {3};
Type = LowPass;
};
//WriteMarkerDataToFilesOnOff = Off;
//MarkerScaleXYZ = {0.025, 0.025, 0.025};
MarkerRGB = {0, 0, 1};
//MarkerDrawOnOff = On;
//MarkerInterPolType = Bspline;
//MarkerBsplineOrder = 8;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 71 of 229

};

Notice that we have also colored the markers blue with the MarkerRGB property and disabled the plot of the 3D trajectories with the ConstructChartOnOff property. We
also set the duration of the movement to automatically fit the C3D file as we have done before:

// The study: Operations to be performed on the model


AnyBodyStudy MyStudy = {
AnyFolder &Model = .MyModel;
Gravity = {0.0, -9.81, 0.0};
AnyIntVar FirstFrame = Main.MyModel.C3D.Header.FirstFrameNo;
AnyIntVar LastFrame = Main.MyModel.C3D.Header.LastFrameNo;
tStart = FirstFrame/Main.MyModel.C3D.Header.VideoFrameRate+2*Kinematics.ApproxVelAccPerturb;
tEnd = LastFrame/Main.MyModel.C3D.Header.VideoFrameRate-2*Kinematics.ApproxVelAccPerturb;
};

Now you should be able to load and run the model and see three blue markers travel through space in a motion that bears some resemblance to a football kick. The three
markers are located on the same segment, and we happen to know that this segment is hinged in its upper end just like the pendulum in the previous lesson, but we do not
know exactly where.

Three markers per segment are typical for many motion capture marker protocols. A segment with no other constraints, i.e. floating freely in space, has six degrees of
freedom. Although each marker provides three constraints, two markers are not enough to determine the location of the segment uniquely. The subtle explanation is that the
markers are not independent because they are located on the same segment and therefore have their mutual distance given. In short, three non-collinear markers is the
minimal set necessary to determine the location in space of an otherwise unconstrained segment.

Three markers then provide a total of nine constraints where the segment only has six DoFs, and the additional information from these markers can be used to determine
other unknown factors in the model.

Let us initially define a segment and some guesses of where the three markers may be located on it:

Main = {

// The actual body model goes in this folder


AnyFolder MyModel = {

// Global Reference Frame


AnyFixedRefFrame GlobalRef = {
}; // Global reference frame

AnySeg Leg = {
Mass = 1;
Jii = {1, 0.01, 1}/15;
AnyRefNode R1 = {
sRel = {0.038, 0.18, 0.022};
};
AnyRefNode R2 = {
sRel = {-0.015, -0.104, 0.028};
};
AnyRefNode R3 = {
sRel = {-0.022, -0.403, -0.023};
};
AnyDrawSeg drw = {};
};

AnyInputC3D C3D = {

Now we just need to use AnyKinDriverMarker objects to tie the marker trajectories to the three points we have defined on the segment and select the solvers for over-
determinate problems exactly as we did in the previous lesson (don’t forget to also select the over-determinate kinematics solver in the study section):

AnyKinDriverMarker C3Dmotion1 = {
AnyRefFrame &Marker = .Leg.R1;
AnyParamFun &Trajectory= Main.MyModel.C3D.Points.Markers.L000.PosInterpol;
AnyDrawKinMeasure drw = {
Label = Off;Size = 0.03;Line = Off;
};

};
AnyKinDriverMarker C3Dmotion2 = {
AnyRefFrame &Marker = .Leg.R2;
AnyParamFun &Trajectory = Main.MyModel.C3D.Points.Markers.L001.PosInterpol;
AnyDrawKinMeasure drw = {
Label = Off;Size = 0.03;Line = Off;
};

};
AnyKinDriverMarker C3Dmotion3 = {
AnyRefFrame &Marker = .Leg.R3;
AnyParamFun &Trajectory = Main.MyModel.C3D.Points.Markers.L002.PosInterpol;
AnyDrawKinMeasure drw = {
Label = Off;Size = 0.03;Line = Off;
};
};

}; // MyModel

// The study: Operations to be performed on the model


AnyBodyStudy MyStudy = {
AnyFolder &Model = .MyModel;
Gravity = {0.0, -9.81, 0.0};
AnyIntVar FirstFrame = Main.MyModel.C3D.Header.FirstFrameNo;
AnyIntVar LastFrame = Main.MyModel.C3D.Header.LastFrameNo;
tStart = FirstFrame/Main.MyModel.C3D.Header.VideoFrameRate+2*Kinematics.ApproxVelAccPerturb;
tEnd = LastFrame/Main.MyModel.C3D.Header.VideoFrameRate-2*Kinematics.ApproxVelAccPerturb;
InitialConditions.SolverType = KinSolOverDeterminate;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 72 of 229

Kinematics.SolverType = KinSolOverDeterminate;
};

Now that we have created the AnyDrawKinMeasure objects, it is no longer necessary to have the points drawn in the C3D object. So let us get rid of them:

AnyInputC3D C3D = {
FileName = "multiple.c3d";
//ReadAllDataOnOff = On;
//TruncateExtraCharsInNamesOnOff = On;
//PointsScaleFactor = 1;
ConstructModelOnOff = Off;
ConstructChartOnOff = Off;
//MarkerUseAllPointsOnOff = Off;
//MarkerUseCamMaskOnOff = On;
//MarkerIndices = ;
//MarkerLabels = ;
//MarkerFilterIndex = 0;
//ProcessedDataFilterIndex = 0;
//AnalogFilterIndex = -1;
Filter = {
AutomaticInitialConditionOnOff = On;
FilterForwardBackwardOnOff = On;
N = 2;
Fc = {3};
Type = LowPass;
};
//WriteMarkerDataToFilesOnOff = Off;
//MarkerScaleXYZ = {0.025, 0.025, 0.025};
MarkerRGB = {1, 0, 0};
//MarkerDrawOnOff = On;
//MarkerInterPolType = Bspline;
//MarkerBsplineOrder = 8;
};

It is now possible to run the Kinematics operation and see the leg segment move with the markers. The actual markers are not visible because they disappear inside the
segment, but if we make the segment semi-transparent, they become visible:

AnySeg Leg = {
Mass = 1;
Jii = {1, 0.01, 1}/15;
AnyRefNode R1 = {
sRel = {0.038, 0.18, 0.022};
};
AnyRefNode R2 = {
sRel = {-0.015, -0.104, 0.028};
};
AnyRefNode R3 = {
sRel = {-0.022, -0.403, -0.023};
};
AnyDrawSeg drw = {
Opacity = 0.5;
};
};

The animation reveals that the leg seems to rotate about the origin of the global reference frame, although we have not explicitly defined any joint. The point must
obviously correspond to some point on the leg segment, but we do not know exactly where that is.

Let us define a joint point at an approximate location on the leg:

AnySeg Leg = {
Mass = 1;
Jii = {1, 0.01, 1}/15;
AnyRefNode Joint = {
sRel = {0, 0.45, 0};
};
AnyRefNode R1 = {
sRel = {0.038, 0.18, 0.022};
};

If you reload and re-run the model, you will see that the new point is approximately but not exactly the point the leg appears to rotate about. We could probably improve

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 73 of 229

the location manually, but let us accept the location for now.

The next step is to create a revolute joint between the new point and the origin of the global reference frame:

AnyRevoluteJoint Joint = {
AnyRefFrame &Ground = .GlobalRef;
AnyRefFrame &Pendulum = .Leg.Joint;
};

AnyInputC3D C3D = {
FileName = "multiple.c3d";

A reload and re-run will reveal that the point is now forced to coincide exactly with the origin of the coordinate system. This is because, as opposed to
AnyKinDriverMarker objects, joints by default contain hard constraints that must be exactly fulfilled. The consequence is that the blue marker dots inside the leg segment
points now seem to deviate a bit further from the center of the points.

There seems to be some unknown location of the joint center on the leg and possibly also of the marker points on the segment that we could either find by experimenting
manually with the local coordinates of the points on the leg segment or, alternatively, ask AnyBody to find for us. We are going to do the latter, and we shall employ a
special study that AnyBody has implemented for the purpose. Please click on the Classes tab in the Tree View on the left hand side of the editor window, expand the Class
List, and scroll down to find the AnyOptKinStudy. Place the cursor after the end brace of the existing AnyBody Study, right-click the AnyOptKinStudy in the Class Tree,
and insert a template of the class:

// The study: Operations to be performed on the model


AnyBodyStudy MyStudy = {
AnyFolder &Model = .MyModel;
Gravity = {0.0, -9.81, 0.0};
tStart = 0.05;
tEnd = 9.95;
InitialConditions.SolverType = KinSolOverDeterminate;
Kinematics.SolverType = KinSolOverDeterminate;
};

AnyOptKinStudy <ObjectName> =
{
//LogFile = "";
/*Analysis =
{
//AnyOperation &<Insert name0> = <Insert object reference (or full object definition)>; You can make any number of these objects!
};*/
//MaxIterationStep = 100;
AnyDesVar &<Insert name0> = <Insert object reference (or full object definition)>;
//AnyDesVar &<Insert name1> = <Insert object reference (or full object definition)>; You can make any number of these objects!

The AnyOptKinStudy’s structure is very similar to the general optimization class AnyOptStudy, but it contains an algorithm specially made for kinematic parameter
optimization and several of the necessary definitions are implicit, so the study is simple to use. All we have to do is to specify the unknown parameters in the model and the
location of the kinematic analysis necessary to evaluate them. We begin with the latter and make the following changes:

AnyOptKinStudy OptKinStudy = {
//LogFile = "";
Analysis = {
AnyOperation &Operation = ..MyStudy.Kinematics;
};
//MaxIterationStep = 100;
AnyDesVar &<Insert name0> = <Insert object reference (or full object definition)>;
//AnyDesVar &<Insert name1> = <Insert object reference (or full object definition)>; You can make any number of these objects!

Now we have specified that we want to optimize parameters to fit the experimental data used in the Kinematics analysis of the original study, i.e. the C3D data. The next
step is to specify which parameters to optimize. In this case, we are uncertain about the precise location of the revolute joint in the upper end of the segment. Its location is
defined by the local coordinates to the AnyRefNode ‘Joint’ on the leg segment:

AnyOptKinStudy OptKinStudy = {
//LogFile = "";
Analysis = {
AnyOperation &Operation = ..MyStudy.Kinematics;
};
//MaxIterationStep = 100;
AnyDesVar Jointx = {
Val = Main.MyModel.Leg.Joint.sRel[0];
};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 74 of 229

This specifies that the zero’th coordinate, i.e. the local x coordinate of the Joint node on the Leg segment is a variable in the problem. Similarly, we can add the y and z
coordinates:

AnyOptKinStudy OptKinStudy = {
//LogFile = "";
Analysis = {
AnyOperation &Operation = ..MyStudy.Kinematics;
};
//MaxIterationStep = 100;
AnyDesVar Jointx = {
Val = Main.MyModel.Leg.Joint.sRel[0];
};
AnyDesVar Jointy = {
Val = Main.MyModel.Leg.Joint.sRel[1];
};
AnyDesVar Jointz = {
Val = Main.MyModel.Leg.Joint.sRel[2];
};
};

Now we can reload the model and a new set of operations will have appeared in the Operation tree on the left hand side of the main frame:

Pick the ParameterOptimization and click the Run button. If you have a ModelView open, you will see the pendulum starting to move and messages about the convergence
of the process will appear in the Report View at the bottom of the screen. Pay close attention to the location of the small blue markers inside the larger yellow dots on the
segment. The blue dots should move considerably closer to the centers of the yellow balls as a consequence of the optimization as shown below, where the left picture is
the location of the markers before the joint location optimization, and the right picture shows the situation after optimization.

This notion is confirmed by opening a new ChartFX view and plotting the development of the objective function of the problem:

The graph shows that the norm of the difference between the measured marker positions and the corresponding nodes on the segment over the entire motion was reduced
from about 0.27 to about 0.01.

Now that we have identified a better location of the joint node on the segment, we might want to save it for later use. This is done by right-clicking the OptKinStudy in the
operations tree on the left hand side of the mainframe and selecting “Save design” from the context menu. This opens a file manager dialogue. Please navigate to the
directory where you keep the model and specify a name for the new file, for instance Opt1.txt.

If you open the new file you can see the saved values:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 75 of 229

Jointx 1.574482553785737e-002

Jointy 4.907793898408988e-001

Jointz 6.508745161899019e-004

You can easily load these values into your model from the same context menu every time you have reloaded the model. Of course, to have the coordinates of the Joint node
permanently updated, you can also simply copy and paste them into the sRel value directly in the Leg segment definition in your AnyScript file. Don’t do it yet, though.
We are going to play a little more with the possibilities.

The optimization we have just completed has presumed that we know well where the markers are located on the segment but are in doubt about the location of the joint,
such as would often be the case in a gait analysis involving a hip joint. However, even if we use a marker protocol that places most markers on well-defined bony
landmarks in the model, there may still be doubt about the precise locations of some or all the markers, and the result of the joint location optimization also shows that
especially the first marker location deviates somewhat from its corresponding AnyRefNode. This indicates that there are other sources of error in the model, than the joint
location, and indeed the recent relocation of the joint may be influenced by errors that are not associated with the joint location. This is the reason why it was advised to not
permanently update the joint location. When the optimization is redefined to also comprise the marker point, it is better to simultaneously optimize the joint position and
marker locations.

The marker node position is included in the optimization in the same way as the Joint node:

AnyOptKinStudy OptKinStudy = {
//LogFile = "";
Analysis = {
AnyOperation &Operation = ..MyStudy.Kinematics;
};
//MaxIterationStep = 100;
AnyDesVar Jointx = {
Val = Main.MyModel.Leg.Joint.sRel[0];
};
AnyDesVar Jointy = {
Val = Main.MyModel.Leg.Joint.sRel[1];
};
AnyDesVar Jointz = {
Val = Main.MyModel.Leg.Joint.sRel[2];
};
AnyDesVar R1x = {
Val = Main.MyModel.Leg.R1.sRel[0];
};
AnyDesVar R1y = {
Val = Main.MyModel.Leg.R1.sRel[1];
};
AnyDesVar R1z = {
Val = Main.MyModel.Leg.R1.sRel[2];
};

Please reload and re-run the ParameterOptimization. The convergence is quite fast and you arrive at the following solution:

The solution appears to be bull’s eye in terms of placing the markers in the center of the yellow nodes. This is confirmed by the optimized value of the objective function:
the residual of the distance between markers and nodes is now less than 0.001.

It appears that we have obtained an almost perfect solution, but why not include all the marker nodes in the optimization? Well, we can try adding another one:

AnyOptKinStudy OptKinStudy = {
//LogFile = "";
Analysis = {
AnyOperation &Operation = ..MyStudy.Kinematics;
};
//MaxIterationStep = 100;
AnyDesVar Jointx = {
Val = Main.MyModel.Leg.Joint.sRel[0];
};
AnyDesVar Jointy = {
Val = Main.MyModel.Leg.Joint.sRel[1];
};
AnyDesVar Jointz = {
Val = Main.MyModel.Leg.Joint.sRel[2];
};
AnyDesVar R1x = {
Val = Main.MyModel.Leg.R1.sRel[0];
};
AnyDesVar R1y = {
Val = Main.MyModel.Leg.R1.sRel[1];

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 76 of 229

};
AnyDesVar R1z = {
Val = Main.MyModel.Leg.R1.sRel[2];
};
AnyDesVar R2x = {
Val = Main.MyModel.Leg.R2.sRel[0];
};
AnyDesVar R2y = {
Val = Main.MyModel.Leg.R2.sRel[1];
};
AnyDesVar R2z = {
Val = Main.MyModel.Leg.R2.sRel[2];
};

When you reload the model and re-run the ParameterOptimization, you will find that the optimization takes much more time, the convergence is much less stable, the
segment moves far away from the marker nodes in the process, and eventually the algorithm gives up with the error message:

Optimization failed : Failed to solve position analysis

You can understand the reason for this behavior if you look at the figure of the previous result above and imagine that we make all four visible points variable, i.e. in a
sense cut them loose from the segment in the optimization problem. Then the segment can float freely in space while the nodes are free to fall exactly on top of their
respective markers and the joint at the origin of the global reference frame. In other words, such a problem has infinitely many perfect solutions and the location of the
segment cannot be determined from the optimization problem. In other words, for a problem like this to be well-posed, some points have to be fixed. When we add the
second marker position to the optimization problem, we leave the model with only two fixed nodes, namely the third marker node and the joint node. This leaves the
segment the opportunity to rotate freely about an axis through the two fixed points, and the optimization problem is ill-posed because it does not determine the rotation of
the segment.

Obviously, in a practical case you would select as the invariable marker nodes those that are physiologically well-determined, for instance from easily accessible bony
landmarks.

Hopefully, this simple, bottom-up example has demonstrated how the technology works. Now, let us change our focus to a top-down approach and see what the technology
can do with real motion capture data. That will be the subject of Lesson 5 .

Lesson 5: Using real data


Without further ado, let us import a C3D file and drive a model. The AnyBody Modeling System offers you virtually unlimited ways of doing things, and probably more
than the average user can comprehend, so we are going to start with a simple and top-down procedure: Version 1.2 of the AnyScript Managed Model Repository, on which
this tutorial is built, which comes with the installation of AnyBody, contains two pre-cooked models that are very easy to drive with your own data and which contain some
really neat features for data processing.

1. Go to the Application\Examples folder to find a folder called GaitLowerExtremity.

2. Take a copy of the entire folder and call it something else, for instance MyGaitModel. You may even want to place it in a new directory parallel to
Application\Examples, for instance Application\MyModels, to avoid polluting the original examples.

3. Browse into the MyGaitModel folder. Please do not be intimidated by the many files it contains; most of them you will never need to touch.

4. Open the file GaitLowerExtremity.Main.any in the AnyBody Modeling System.

As the name indicates, this is a gait model comprising only the lower extremities and the necessary part of the upper body for attachment of muscles. The motion imposed
on the original model is gait over three force platforms, but you can easily modify this to any other movement, simply by importing a different C3D file to drive the model
with.

In the top of the file you find a brief description of the procedure. Don’t worry about that for now, but browse a little further down to find this:

//**************************************************
//Set this to one if you want to run the motion and Parameter Optimization identification
#define MotionAndParameterOptimizationModel 0

//Set this to one if you want to run the inverse dynamic analysis
#define InverseDynamicModel 1
//Usually only have one of the two switches active
//***************************

These lines define the two model executions that you normally have to perform to process a new data set. When MotionAndParameterOptimizationModel=1, the system
performs an optimization of the model to fit the C3D data you have recorded. This is much more than simply making the model follow the marker trajectories; it also
optimizes the model parameters such as segment lengths and marker placements, based on the recorded data.

If InverseDynamicModel=1, then the system performs an actual dynamic analysis based on the parameters identified in the MotionAndParameterOptimization step.

Please make sure you have set the following:

//**************************************************
//Set this to one if you want to run the motion and Parameter Optimization identification
#define MotionAndParameterOptimizationModel 1

//Set this to one if you want to run the inverse dynamic analysis
#define InverseDynamicModel 0
//Usually only have one of the two switches active
//***************************

Now please load the model and open up a new Model View. You should see the following skeleton without arms:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 77 of 229

If you look closely, you can see that the skeleton is equipped with markers and if you zoom in a little, you can also see that that the markers carry small coordinate systems
with red and green arrows.

These are the marker points defined on the human body, and the red and green arrows designate directions in which the marker position is fixed versus free to be
optimized. A free marker position is one that is not well-known by the clinician.

So why would we be in doubt about the position of a marker that we have placed? Well, clinicians place markers on the skin at an unknown distance from the bone, and
even when a marker is placed on a bony landmark just below the skin, we are never quite sure which point that corresponds to in the bone’s local coordinate system. If we
get those points wrong, the resulting motion of the model will also be inaccurate.

So the green arrows designate directions in which we have the greatest uncertainty about whether the marker is placed in the model as it was in the experiment. The good
news is that we can optimize those marker placements exactly as we did in lesson 4 . The model is set up to do this automatically, and if you are happy with the choice that
has been made, you need not do anymore. Of course, if you use a different marker protocol there will be additional setting up to do, but only once until you have
determined the parameterization that fits your protocol. In the interest of simplicity, we shall postpone the discussion of marker protocol setup.

In addition to the marker coordinates, the model considers the segment lengths to be variable, so the computation we are about to do will also automatically figure out how
long the segments are, and thereby where the joints are placed. Pretty much any parameter in a model can be made variable but not all parameters will be determined well
by the marker trajectory data and not all parameters can be determined at the same time because the mocap data only contains limited information and because some
parameters can create mutual indeterminacies. For instance, if the model has no movement of a specific joint, then it is not possible to get information about the location of
that joint or about the lengths of adjacent segments from the marker data.

Without further ado, let us perform the optimization:

In the Operation Tree you find the MotionAndParameterOptimizationSequence. Select it and click the “Run” button.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 78 of 229

You will see the model walking repeatedly over the force platforms, sometimes slowly and sometimes a bit faster depending on the speed of your computer and the
progress of the computation. The optimization will take a few minutes to complete and it is speeded up significantly if you switch the Model View update off during the
process. The final message you get is:

#### Macro command > classoperation Main.Studies.ParameterIdentification "Save design" --file="GaitNormal0003-processed-OptimizedParametersTest.txt"

Main.Studies.ParameterIdentification : Saving design...

It means that things have gone fine, the optimization has converged, and the optimized values of the variable parameters have been saved on a text file for later use.

Before we continue, let us ponder for a moment when it is necessary to perform this optimization. The results of the optimization in summary are the following:

1. Updated anthropometrical parameters.

2. Updated marker locations.

3. The movement.

Within a brief time we can safely presume that the first is constant for a particular test subject. This means that if we have once and for all determined and saved the
anthropometrical parameters of this subject, then we probably need not include them in the optimization again.

We can usually presume that the marker locations on the body are constant within a given trial or series of trials performed with the same subject with the same markers
attached. However, if the markers have been detached or relocated, then obviously the optimization of marker positions must be done again.

Finally, the movement is different for each trial, so this part of the optimization we have to do again for each new recording. However, for most cases, the computational
effort of performing the optimization with all the parameters is modest, to the casual user may elect to simply redo the full optimization for each trial as we shall do later in
this tutorial.

Let us now run the actual inverse dynamics analysis. We must first change the settings in the main file:

//**************************************************
//Set this to one if you want to run the motion and Parameter Optimization identification
#define MotionAndParameterOptimizationModel 0

//Set this to one if you want to run the inverse dynamic analysis
#define InverseDynamicModel 1
//Usually only have one of the two switches active
//***************************

After reload, a new model including muscles and a new operation are available:

This operation contains everything that is necessary to run the analysis: It loads the optimized model parameters that were saved previously; if necessary, it performs
calibration movements to adjust the tendon lengths to the lengths of the bones; and finally executes a dynamic analysis to determine forces in the system. Click the
InverseDynamicAnalysisSequence and then click the “Run” button.

The model starts walking across the force platforms. It walks slowly due to the very high amount of detail of the model, requiring the computer to continuously calculate

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 79 of 229

forces in more than 300 muscles. When the analysis is finished, you can open up a ChartFX view and investigate the results, for instance the hip joint reaction forces:

Importing new motion data

So we have seen the model optimize its parameters and we have seen it perform a dynamic analysis on existing data that somebody else has defined. But here comes the
real point of the application:

Processing a different motion is exactly the same !

All we have to do is replace the C3D file containing the motion data. The GaitLowerExtremity folder already contains a few C3D files that we can try. All we have to do is
make the model point at a different file. A few lines into the Main file, you find this:

#include "TrialSpecificData.any"

This file contains the settings you typically want to change when

Double-click the TrialSpecificData.any file name, and the file opens up in a new window. Then, just a few lines down, refer to the new filename into the model:

//Name of the C3D file to be analysed


AnyString NameOfFile ="GaitFast0001-processed"; //Write the name of the file here

Since this is a new C3D file from a new trial, we also need to run the kinematic optimization again, so we change the setting in the main file back to the
MotionAndParameterOptimization option:

//Set this to 1 if you want to run the motion and Parameter Optimization identification
//**************************************************
#define MotionAndParameterOptimizationModel 1

//Set this to 1 if you want to run the inverse dynamic analysis


#define InverseDynamicModel 0

This is all there is to it. We can now reload the model. To see the model moving (without doing the parameter optimization just now), locate and run the Kinematics
operation in the Operation tree:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 80 of 229

The movement seems to work fine and you will notice that this gait pattern is a little different from before. The steps are longer and the posture indicates that this is a
person in a hurry.

Now is the time to run the MotionAndParameterOptimizationSequence. It takes a bit of time, and again you can speed up the process by switching off the update of the
ModelView window. Eventually, the process comes to an end and you get the message:

Optimization converged

**********************************************************************

#### Macro command > runmacro "SaveMacroOperation-Save.anymcr"

#### Macro command > classoperation Main.ModelSetup.SaveMacroOperation "Save AnyString to file" --file="RunMacroOperation-Save.anymcr"

#### Macro command > runmacro "RunMacroOperation-Save.anymcr"

#### Macro command > classoperation Main.Studies.ParameterIdentification "Save design" --file="GaitFast0001-processed-OptimizedParameters.txt"

Main.Studies.ParameterIdentification : Saving design...

#### Macro command > operation Main.Studies.MotionOptimization.Kinematics

#### Macro command > run

So we can change the model setting in the Main file again, reload and run the actual analysis, i.e. the InverseDynamicAnalysisSequence operation:

//**************************************************
//Set this to one if you want to run the motion and Parameter Optimization identification
#define MotionAndParameterOptimizationModel 0

//Set this to one if you want to run the inverse dynamic analysis

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 81 of 229

#define InverseDynamicModel 1
//Usually only have one of the two swicthes active
//**************************************************

Which, after the analysis can provide a new hip joint force profile documenting that faster gait leadt to higher hip joint forces.

Using full-body models

Many motion experiments deal with the entire body as opposed to just the lower extremities. The AnyScript Model Repository contains another pre-cooked model for this
purpose, and it will reveal that there is more data in the C3D file we just imported than we saw in the GaitLowerExtremity model.

To get set up, do the following:

1. Go to the Application\Examples folder to find a folder called GaitFullBody.

2. Take a copy of the entire folder and place it next to the MyGaitLowerExtremity model under a new name, for instance MyGaitFullBody.

3. Browse into the MyGaitFullBody folder and open the file GaitFullBody.Main.any in the AnyBody Modeling System.

4. Imitating the previous procedure, make the following changes in the files:

In GaitFullBody.main.any, make sure the MotionAndParameterOptimizationModel is the active operation:

//Set this to 1 if you want to run the motion and Parameter Optimization identification
//**************************************************
#define MotionAndParameterOptimizationModel 1

//Set this to 1 if you want to run the inverse dynamic analysis


#define InverseDynamicModel 0
//Usually only have one of the two swicthes active so set the inactive analysis to 0
//**************************************************

In TrialSpecificData.any, refer to the new c3d file:

<AnyFolder TrialSpecificData={

//Name of the C3D file to be analysed


AnyString NameOfFile ="GaitFast0001-processed"; //Write the name of the file here

Please load the model and open a Model View if you do not already have one. You will see the model as before, but now with the arms included.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 82 of 229

Select and run the RunMotionAndParameterOptimizationSequence in the Operations tree:

The model starts walking repeatedly over the force platforms including the arm motions while it tries to optimize segment lengths and marker positions. It takes three
iterations and a little more time than before to optimize the model because this is a much larger problem, but as before you can speed up the process if you switch off the
update of the ModelView Window. It is possible to monitor the convergence of the optimization problem from a ChartFX window like this:

Eventually, the optimization process terminates and you can switch to the InverseDynamicAnalysis:

//Set this to 1 if you want to run the motion and Parameter Optimization identification
//**************************************************
#define MotionAndParameterOptimizationModel 0

//Set this to 1 if you want to run the inverse dynamic analysis


#define InverseDynamicModel 1
//Usually only have one of the two switches active so set the inactive analysis to 0
//**************************************************

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 83 of 229

… and perform the analysis of the entire body including the muscle forces. This full-body model with almost 1000 muscles included takes considerable time to analyze but
will reward you with very detailed information about the function of the muscle system in gait as illustrated below.

In the next lesson we shall learn how to use weight functions to deal with markers dropping out of the measurements. This happens frequently in motion capture
experiments and you can read all about in Lesson 6 .

Lesson 6: Weight functions


In this lesson, we shall learn how to use weight functions on kinematic drivers. This is useful in over-determinate kinematic analysis where we might want to let some
drivers have more significance than others. Without really discussing it, we used unity weights on all our soft kinematic constraint equations in the previous lessons, but
this is not always the best choice as we shall see in this lesson.

So what are weight functions and what can they be used for? In general the weights can be used to put more emphasis on some kinematic constraint equations than on
others. This will force the motion of the model closer to the constraints with the higher weight. The two most obvious places where these weight functions can be used are:
1) when you trust one kinematic constraint more than another, e.g. if some markers are more reliable than others. 2) If you have a marker temporarily dropping out of sight
of the cameras, then you can temporarily assign it a weight of zero, which will eliminate it from the model in the interval where it is invalid. There are of course many other
possible uses of weight functions, but we shall concentrate on markers in the following.

So without further ado, let us look into how to use a weight function to deal with a marker dropping out. The data we are going to use is the same pendulum example as
used previously but with marker L002 modified to drop out in the interval from 4.20 s to 4.76 s.

Please download and save the file multiple_with_dropout.c3d .

Then close all open windows in AnyBody and create a new Main file by clicking the ‘M’ tool button in the upper left hand corner of the main frame. This creates an empty
model into which you can insert an AnyInputC3D object, refer to the multiple_with_dropout.c3d file and specify the filter as we did before:

Main = {

// The actual body model goes in this folder


AnyFolder MyModel = {

// Global Reference Frame


AnyFixedRefFrame GlobalRef = {

// Todo: Add points for grounding of the model here

}; // Global reference frame

AnyInputC3D C3D =
{
FileName = "multiple_with_dropout.c3d";
//ReadAllDataOnOff = On;
//TruncateExtraCharsInNamesOnOff = On;
//MakeNameUniqueStr = "_";
//PointsScaleFactor = 1;
//ConstructModelOnOff = On;
//ConstructChartOnOff = On;
//ConstructWeightFunUsingResidualOnOff = Off;
//MarkerUseAllPointsOnOff = Off;
//MarkerUseCamMaskOnOff = On;
//MarkerIndices = {};
//MarkerLabels = {};
//MarkerFilterIndex = 0;
//ProcessedDataFilterIndex = 0;
//AnalogFilterIndex = -1;
Filter =
{
AutomaticInitialConditionOnOff = On;
FilterForwardBackwardOnOff = On;
N = 2;
Fc = {3};
Type = LowPass;
};
//WeightThreshold = 0;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 84 of 229

//WeightOutput = {{0, 1}, {0, 1}, {0, 1}};


//WeightTransitionTime = 0.1;
//SearchAndReplace = {};
//WriteMarkerDataToFilesOnOff = Off;
//MarkerScaleXYZ = {0.025, 0.025, 0.025};
MarkerRGB = {0, 0, 1};
//MarkerDrawOnOff = On;
//MarkerInterPolType = Bspline;
//MarkerBsplineOrder = 8;
};

Notice that we have also colored the markers blue with the MarkerRGB property. We also set the duration of the movement to automatically fit the C3D file as we have
done before:

// The study: Operations to be performed on the model


AnyBodyStudy MyStudy = {
AnyFolder &Model = .MyModel;
Gravity = {0.0, -9.81, 0.0};
AnyIntVar FirstFrame = Main.MyModel.C3D.Header.FirstFrameNo;
AnyIntVar LastFrame = Main.MyModel.C3D.Header.LastFrameNo;
tStart = FirstFrame/Main.MyModel.C3D.Header.VideoFrameRate+2*Kinematics.ApproxVelAccPerturb;
tEnd = LastFrame/Main.MyModel.C3D.Header.VideoFrameRate-2*Kinematics.ApproxVelAccPerturb;
};

Now you should be able to load and run the model and see three blue markers travel through space in a motion that bears some resemblance to a football kick as you did
previously. However, notice how the L002 marker drops out. Many motion capture systems flag invalid markers in the C3D file by setting the residual property to -1 for
the affected frames. If you click the Model tab, open MyModel, C3D, Points, Markers, and L002, you will find the Residual property. If you double-click it and scroll
through it, you will see that there is an interval, where it has the value -1.

This information we are going to use later to construct a weight function for this marker.

Let us initially define a segment with the three markers located on it, ground it with a revolute joint and drive it using the marker data using the AnyKinDriverMarker
object as we did in lesson four:

AnySeg Leg = {
Mass = 1;
Jii = {1, 0.01, 1}/15;
AnyRefNode R1 = {
sRel = {0.038, 0.18, 0.022};
};
AnyRefNode R2 = {
sRel = {-0.015, -0.104, 0.028};
};
AnyRefNode R3 = {
sRel = {-0.022, -0.403, -0.023};
};
AnyRefNode Joint = {
sRel = {0, 0.45, 0};
};
AnyDrawSeg drw = {Opacity = 0.5;};
};

AnyRevoluteJoint Joint = {
AnyRefFrame &Ground = .GlobalRef;
AnyRefFrame &Pendulum = .Leg.Joint;
};

AnyKinDriverMarker C3Dmotion1 = {
AnyRefFrame &Marker = .Leg.R1;
AnyParamFun &Trajectory= Main.MyModel.C3D.Points.Markers.L000.PosInterpol;
AnyDrawKinMeasure drw = {
Label = Off;Size = 0.03;Line = Off;
};

};
AnyKinDriverMarker C3Dmotion2 = {
AnyRefFrame &Marker = .Leg.R2;
AnyParamFun &Trajectory = Main.MyModel.C3D.Points.Markers.L001.PosInterpol;
AnyDrawKinMeasure drw = {
Label = Off;Size = 0.03;Line = Off;
};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 85 of 229

};
AnyKinDriverMarker C3Dmotion3 = {
AnyRefFrame &Marker = .Leg.R3;
AnyParamFun &Trajectory = Main.MyModel.C3D.Points.Markers.L002.PosInterpol;
AnyDrawKinMeasure drw = {
Label = Off;Size = 0.03;Line = Off;
};
};

}; // MyModel

Now that we want to drive a segment with the markers rather than just look at the markers themselves, we also need to ask for the soft kinematics solver in the study
section:

// The study: Operations to be performed on the model


AnyBodyStudy MyStudy = {
AnyFolder &Model = .MyModel;
Gravity = {0.0, -9.81, 0.0};
AnyIntVar FirstFrame = Main.MyModel.C3D.Header.FirstFrameNo;
AnyIntVar LastFrame = Main.MyModel.C3D.Header.LastFrameNo;
tStart = FirstFrame/Main.MyModel.C3D.Header.VideoFrameRate+2*Kinematics.ApproxVelAccPerturb;
tEnd = LastFrame/Main.MyModel.C3D.Header.VideoFrameRate-2*Kinematics.ApproxVelAccPerturb;
InitialConditions.SolverType = KinSolOverDeterminate;
Kinematics.SolverType = KinSolOverDeterminate;
};

Please do not forget to change to the over-determinate kinematics solver.

Now that we have created the AnyDrawKinMeasure objects, it is no longer necessary to have the points drawn in the C3D object. So let us get rid of them:

AnyInputC3D C3D =
{
FileName = "multiple_with_dropout.c3d";
//ReadAllDataOnOff = On;
//TruncateExtraCharsInNamesOnOff = On;
//MakeNameUniqueStr = "_";
//PointsScaleFactor = 1;
ConstructModelOnOff = Off;
//ConstructChartOnOff = On;
//ConstructWeightFunUsingResidualOnOff = Off;
//MarkerUseAllPointsOnOff = Off;
//MarkerUseCamMaskOnOff = On;
//MarkerIndices = {};
//MarkerLabels = {};
//MarkerFilterIndex = 0;
//ProcessedDataFilterIndex = 0;
//AnalogFilterIndex = -1;
Filter =
{
AutomaticInitialConditionOnOff = On;
FilterForwardBackwardOnOff = On;
N = 2;
Fc = {3};
Type = LowPass;
};
//WeightThreshold = 0;
//WeightOutput = {{0, 1}, {0, 1}, {0, 1}};
//WeightTransitionTime = 0.1;
//SearchAndReplace = {};
//WriteMarkerDataToFilesOnOff = Off;
//MarkerScaleXYZ = {0.025, 0.025, 0.025};
MarkerRGB = {0, 0, 1};
//MarkerDrawOnOff = On;
//MarkerInterPolType = Bspline;
//MarkerBsplineOrder = 8;
};

It should now be possible to load the model and run the kinematic analysis. If you open the ModelView, you should see something like this:

You should see a large change in the otherwise smooth motion of the pendulum, when marker L002 drops out, which it does by going to position (0.0,-0.2,0.0). Since this

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 86 of 229

configuration of the three markers is not compatible with the rigid multi-body model with its imposed revolute joint constraint, the result is that the pendulum is located
somewhere in between all three markers.

If you plot the acceleration of the segment, by opening a ChartFX and going to MyStudy, Output, Model and Leg where you can find the rDDot property.

This shows some large acceleration peaks of the segment when the marker drops out.

So how can we deal with this problem? We can do this by using built-in functionality in the C3D object to construct a weight function that is zero in the interval where the
marker is invalid and one otherwise, except for a transition phase between the two. To do this, we have to use the ConstructWeightFunUsingResidualOnOff setting in the
C3D object.

AnyInputC3D C3D =
{
FileName = "multiple_with_dropout.c3d";
//ReadAllDataOnOff = On;
//TruncateExtraCharsInNamesOnOff = On;
//MakeNameUniqueStr = "_";
//PointsScaleFactor = 1;
ConstructModelOnOff = Off;
//ConstructChartOnOff = On;
ConstructWeightFunUsingResidualOnOff = On;
//MarkerUseAllPointsOnOff = Off;

By default, this creates a weight function for each marker, which assigns value one when the residual is positive and zero when it is negative with a transition time between
the two states of 0.1 s.

Now, all we have to do is link the weight function to the kinematic constraint equation, where it should be used. In our model, this means that we have to make the
WeightFun member of the AnyKinDriverMarker object for L002 point to the weight function for L002 in the C3D file. The weight function is called Weight located in the
same folder as the PosInterpol.

AnyKinDriverMarker C3Dmotion3 = {
WeightFun = {&Main.MyModel.C3D.Points.Markers.L002.Weight};
AnyRefFrame &Marker = .Leg.R3;
AnyParamFun &Trajectory = Main.MyModel.C3D.Points.Markers.L002.PosInterpol;
AnyDrawKinMeasure drw = {
Label = Off;Size = 0.03;Line = Off;
};

If we reload and run the kinematic analysis again, we will see a much more smooth motion, but if the acceleration is plotted again, then it is clear that it is not perfect:

The graph looks similar to before, but the values on the ordinate axis are much smaller. The remaining problem is related to the transition time for switching the marker in
and out. To investigate this in more detail, we need graphs of the weight function as well as the trajectory of the marker. Try including these lines in your model:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 87 of 229

AnyFloat EvalWeight = Main.MyModel.C3D.Points.Markers.L002.Weight(Main.MyStudy.t);


AnyFloat EvalTrajectory = Main.MyModel.C3D.Points.Markers.L002.PosInterpol(Main.MyStudy.t);

AnyInputC3D C3D =

What this code does is that it evaluates the Weight and PosInterpol parameter functions at all time steps in the analysis. Hereby, we can plot them both after a kinematic
analysis. Try reloading the model, re-running the kinematic analysis, and then plot each of these two functions by browsing to them using two separate ChartFX windows.
You should now be able to see something like this:

What has happened is that the filtering and the interpolation of the marker trajectory have smoothed the drop out transition and even introduced small peaks before and
after the marker data really disappear as given by the Residual. Therefore, we need to make the period, in which the marker is assigned low weight, longer. To do this, we
simply extend the transition period a bit using the WeightTransitionTime in the C3D object:

AnyInputC3D C3D =
{
FileName = "multiple_with_dropout.c3d";
//ReadAllDataOnOff = On;
//TruncateExtraCharsInNamesOnOff = On;
//MakeNameUniqueStr = "_";
//PointsScaleFactor = 1;
ConstructModelOnOff = Off;
//ConstructChartOnOff = On;
ConstructWeightFunUsingResidualOnOff = On;
//MarkerUseAllPointsOnOff = Off;
//MarkerUseCamMaskOnOff = On;
//MarkerIndices = {};
//MarkerLabels = {};
//MarkerFilterIndex = 0;
//ProcessedDataFilterIndex = 0;
//AnalogFilterIndex = -1;
Filter =
{
AutomaticInitialConditionOnOff = On;
FilterForwardBackwardOnOff = On;
N = 2;
Fc = {3};
Type = LowPass;
};
//WeightThreshold = 0;
//WeightOutput = {{0, 1}, {0, 1}, {0, 1}};
WeightTransitionTime = 0.8;
//SearchAndReplace = {};
//WriteMarkerDataToFilesOnOff = Off;
//MarkerScaleXYZ = {0.025, 0.025, 0.025};
MarkerRGB = {0, 0, 1};
//MarkerDrawOnOff = On;
//MarkerInterPolType = Bspline;
//MarkerBsplineOrder = 8;
};

If we reload and run the kinematic analysis, we should now see the pendulum moving smoothly and it is almost impossible to detect in the motion that the marker
disappears. If we plot the segment acceleration again, we see that we no longer have any of the peaks around the drop out of the marker:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 88 of 229

Hopefully, this simple example has demonstrated how the weight functions works. In fact, the WeightFun members of the AnyKinMarkerDriver class come from the
parent class AnyKinEq such that all kinematic constraint equations can be assigned a weight; not only markers. Also, WeightFun is a pointer to a ParamFun, which means
that all AnyScript parameter functions can be used as weights. In other words, you can design your own weight function using any of the parametric function types in the
system.

The final lesson of this tutorial is about problems that may arise with C3D files. Please continue to Lesson 7 .

Lesson 6: Troubleshooting C3D files


Occasionally you may experience problems reading C3D files and some of the common issues are treated below. But before we get to them, let us review a few facts about
the C3D format. The C3D format is a public domain, binary file format that has been used in Biomechanics, Animation and Gait Analysis laboratories to record
synchronized 3D and analog data since the mid 1980's. It is supported by all major Motion Capture System manufacturers, as well as other companies in the
Biomechanics, Motion Capture and Animation Industries, and there is a web site and community devoted to its maintenance: www.c3d.org .

The fact that the format is binary means that you cannot open a C3D file and read it unless you have a special reader. There are readers available at the c3d.org website, and
most motion capture systems come with software that reads and manipulates C3D files.

The fact that the file format is old and also designed to work on just about every conceivable computer system means that it has a rather complex structure and that there
are rigid and precise rules for the creation of C3D files. An unfortunate consequence of this is that the format is error prone in the sense that not all software systems create
C3D files that live completely up to the standard. The AnyInputC3D class in AnyBody is designed to cope with most of the common deviations from the standard, but
occasionally you may run into a problem. Here are some of the common problems and solutions:

I know my C3D file contains data, but I cannot see any markers moving anywhere in the ModelView.

There are two usual causes for this problem. The first one is a scaling issue. Data in C3D files is often in millimeters while standard settings in AnyBody such as coordinate
system sizes, marker sizes and such are scaled to fit to a human-size model in meters. If AnyBody reads a file in millimeters and interprets the result as meters, then the
markers will be very far apart, and if you Zoom All in the model view, the markers may be so small compared to the viewed space that you cannot see them.

The remedy is to set the PointScaleFactor in the AnyInputC3D object to 0.001, for instance, in the case of data in millimeters.

The second frequent explanation is that a C3D file contains two data sections: one for raw data and one for processed data. By default, AnyBody creates markers based on
raw data, but if your C3D file has been processed by other software prior to being read by AnyBody, then the other software may have moved the marker data to the
processed section leaving you with nothing in your model.

The remedy is to set

MarkerUseAllPointsOnOff = On;

which instructs AnyBody to read data from both the raw and the processed data sections.

I get an error message when I load the model.

Many things can go wrong when loading a C3D file, simply because the format of the file is relatively complex. The aim has been to make AnyBody tolerant of some of
the more usual deviations from the standard, but sometimes things are irreparably wrong with the file and you will end up with an error message that ideally should give
you a hint of what the problem is.

If you get an error message stating that the file cannot be opened, that it is not a C3D file, or that the file is corrupt, then you likely have to go back to your source and find
out whether the data you have been given has somehow been damaged.

Another class of error messages deal with specific problems with the file, for instance that a required section or header is missing. This can mean that AnyBody does not
have the necessary information to process the file and has to give up.

The markers I get in my loaded model have different names from what I expected.

When you have loaded a C3D file into an AnyBody model, the object can subsequently be browsed in the Model Tree in the left hand side of the screen. Markers in C3D
files have user-defined names for easier identification, and sometimes you will find that the names you get in the AnyBody Model Tree are not the same as you defined in
your experiment. There are two possible reasons for this:

The first reason is that AnyScript is a programming language and has rules about allowed characters in names. So if the marker names in the C3D file contain characters
that have a special meaning, for instance ‘*’ or ‘+’, then they are automatically replaced by a text string of the decimal ASCII code of the sign surrounded by underscores,
for instance _42_ instead of ‘*’.

The second possible reason is more subtle. The C3D standard has a liberal length constraint (128 characters) on names of markers, but the experimental community often
uses strings of just four characters to name markers, and this implicit convention has influenced some types of software to truncate marker labels to four characters. So, if
you have named your markers “MARKERRKNEE”, “MARKERLKNEE”, “MARKERSTERNUM” and so on, and your C3D file somewhere in the pipeline from
experiment to AnyBody passes through a piece of software that truncates the names, then AnyBody will be given a C3D file where all the marker names are truncated to
just “MARK”. AnyBody will not accept non-unique marker names and therefore renames them automatically.

Inverse dynamics of Muscle Systems


The AnyBody Modeling System performs inverse dynamics as one of its central operations. In biomechanics, inverse dynamics is traditionally understood at the process of
computing from measured ground reaction forces in a gait analysis to net moments in the anatomical joints.

At least in AnyBody context, inverse dynamics is much more than that. In brief, inverse dynamics allows you to simulate muscle and joint forces in the entire body
undergoing complex movements, taking dynamic inertia forces in to account, and not necessarily requiring measured forces in the interface between the body and the
environment. Inverse dynamics had the advantage that it allows for analysis of very complicated musculoskeletal systems comprising hundreds of muscles on desktop or
laptop computers in a few seconds.

The figure below illustrates the simple principle behind inverse dynamics.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 89 of 229

If we know the magnitude of the external force, and we know the length of the forearm and the insertion point of the biceps muscle on the forearm, then it is not difficult to
compute the muscle force from simple moment equilibrium about the elbow. Further equilibrium equations can subsequently give us the reaction forces in the elbow joint.

This is really the principle of inverse dynamics as it takes place in the AnyBody Modeling System. So why do we need to make these computations with advanced
software? Well, there are several complications that make realistic cases somewhat more challenging. The figure below illustrates some of them.

This figure is a much more anatomically realistic representation of the mechanics of a human upper extremity. Even if we count only from the gleno-humeral joint to the
wrist, thus disregarding the shoulder girdle and the hand, the arm will have seven independent degrees of freedom, i.e. seven different joint articulations, and not just one,
as we implicitly assumed in the simple examples before. Moreover, many more muscles than the single biceps from the previous figure are involved in flexing the elbow,
and many of these muscles span several joints. It even turns out that some of the muscles will end up working antagonistically, i.e. against each other. The multiple degrees
of freedom and multiple muscles directly lead to a much larger system of equilibrium equations that have to be formulated and solved, and this is not something that can be
done easily by hand.

Another complication is that many muscles are wrapping over bones on their way from origin to insertion. This complicates the mechanics of the problem significantly
because the muscle path is not easy to predict and because the muscle provides force to the bone it is wrapping over and not just at its origin and insertion points.

For obvious graphical reasons, the figure shown here does not move as living bodies usually do. Movement also complicates the case significantly by adding inertia forces
to the problem and by changing the equilibrium equations from one time step to the next. The bottom line is that it is virtually impossible to simulate realistic
musculoskeletal systems “by hand” or even develop them bottom-up by general mathematical software. The only viable solution is to use a computer system designed for
this particular purpose, so here we are. With the AnyBody Modeling System you can easily define very complex musculoskeletal systems and analyze them dynamically as
you have probably already done in the Getting Started tutorial. If not, now would be a good time to do it and familiarize yourself with the mouse clicks necessary to
conduct the InverseDynamics operation and inspect the results before continuing with the next steps of this tutorial.

There is one more complexity that has not been mentioned yet: The body has many more muscles than strictly necessary to balance its degrees of freedom, and this means
that there are infinitely many different ways the body can recruit its muscles to get the job done. The understanding of this problem and how it is dealt with in the AnyBody
Modeling System is so important that the rest of this tutorial is dedicated to the problem. We are going to take a deductive approach because it is necessary for a reasonable
understanding of the physiological assumptions behind the entire field of muscle recruitment. More on this topic can be found in the recorded previous webcast on
“Features of muscle recruitment algorithms“ here .

Let us begin with Lesson 1: The basics of muscle recruitment .

Lesson 1: The basics of muscle recruitment


Muscle recruitment in inverse dynamics is the process of determining which set of muscle forces will balance a given external load. If we take the trouble of setting up the
system of equilibrium equations for a musculoskeletal system by hand, then we can organize them on the following form:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 90 of 229

where f is a vector of muscle and joint forces, r is a vector representing the external forces and inertia forces, and C is a matrix of equation coefficients. In other words,
equilibrium always results in a linear system of equations that should be easy to solve. Unfortunately, it is not, and this is due to two reasons.

The first reason is that muscles are unilateral element that can only pull and not push. So the part of r that is muscle forces is restricted in sign, and only solutions with
positive or zero muscle forces are physiologically reasonable.

The second reason is known as muscle redundancy. It is due to the fact that muscle systems tend to have many more muscles than strictly necessary to balance the external
forces. The mathematical consequence is that the equilibrium equation above has more unknowns than it has equations and therefore usually infinitely many solutions.

So, is muscle recruitment in the living human body random in the sense that it just chooses the first and the best solution that balances the load? Experiments show that this
is not the case. In skilled movements, muscles tend to be recruited systematically, so there is some criterion behind the central nervous system’s choice of muscle
activations. Mathematically we can formulate the choice between the infinitely many solutions as an optimization problem in the following way:

The equilibrium equations are constraints in this problem: whatever solution we find must balance the external forces. The requirement for positive muscle forces has also
been added as a constraint to the problem. Only solutions adhering to these two requirements are acceptable, but out of these many solutions we are going to change the
one that minimizes the function G , and are furthermore going to anticipate that this function depends on the muscle forces. This seems reasonable because muscle
recruitment is probably a result of biological adaptation and muscle work is costly for the organism and should be minimized in an environment where resources are
limited. Now we just have to figure out what the function G actually is and unfortunately there is nobody around who knows it for sure.

So in the following we are going to play around with different choices and see what happens. AnyBody is great for this purpose because the settings of the
InverseDynamics operation offer the user a lot of freedom to choose the function he or she believes is the right one for a given purpose.

So let’s get set up with a model that is suitable for experimentation with different definitions of the muscle recruitment problem. We shall begin with one that is very, very
simple and work our way upwards from there. Please download right-click this link and save the file in a working area of your hard disk: Recruitment.Main.any .

Open the model in the AnyBody Modeling System, load it into memory, open a ModelView window, select the InverseDynamics operation, and click the Run button. You
should see something like this:

The thick blue rod is an arm hinged at its left end to the origin of the global reference frame. A muscle is attached at the other end and the muscle elevates the arm against
gravity.

Please click Window->ChartFX (2D) to open up a new window for inspection of results. You can expand the tree on the left hand side of that window and find the muscle
force, Fm, somewhere inside the properties of the M1 muscle. When you click it you get a graphical representation of the muscle force:

Obviously, AnyBody has solved the equilibrium equations and has determined what the muscle force is at every instant of the simulation time. But which objective
function, G , has the system used?

If we review this problem we can see that it has only a single degree of freedom and only a single muscle to carry the load. This actually means that the equilibrium
equations are determinate (one degree of freedom and one muscle) and in this case it does no matter what G is, so there is little we can do in the settings to influence the
result of the analysis. The result is given by equilibrium alone and there is no other muscle force than the one you see in the graph that would be able to balance the model.
It does not get really interesting until we apply another muscle. A couple of simple additions to the model will accomplish this. We first add a new origin node on the
global reference frame:

Main = {

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 91 of 229

// The actual body model goes in this folder


AnyFolder MyModel = {

// Global Reference Frame


AnyFixedRefFrame GlobalRef = {
AnyDrawRefFrame drw = {
ScaleXYZ = {1,1,1}/10;
RGB = {1,0,0};
};
AnyRefNode M1 = {
sRel = {0, 0.05, 0};
};
AnyRefNode M2 = {
sRel = {0, 0.03, 0};
};
}; // Global reference frame

Then we define a second muscle by copying the first one and making a few changes. Notice that the strength of the second muscle is set to half of the strength of the first
one:

AnyViaPointMuscle M1 = {
AnyMuscleModel Model = {
F0 = 100;
};
AnyRefFrame &Ori = .GlobalRef.M1;
AnyRefFrame &Ins = .Seg.M;
AnyDrawMuscle drw = {
Bulging = 1;
MaxStress = 1e5;
};
};

AnyViaPointMuscle M2 = {
AnyMuscleModel Model = {
F0 = 50;
};
AnyRefFrame &Ori = .GlobalRef.M2;
AnyRefFrame &Ins = .Seg.M;
AnyDrawMuscle drw = {
Bulging = 1;
MaxStress = 1e5;
};
};

Now two muscles will have to cooperate on the task of carrying one degree of freedom. Let us see what AnyBody, in the absence of any special specifications from the
user, chooses to do. If you load and run the model, plot the muscle force of M1 as you did before, and then manually place an asterisk in place of the muscle name in the
specification line in the ChartFX window, you should get something like this:

We can observe that both muscles are working and that M1, which has the higher strength and better moment arm, is exerting more force than the weaker M2. This seems
immediately reasonable from a physiological point-of-view, and this is what you get from AnyBody if you do not make any special specifications. We shall get back to the
precise nature of AnyBody’s standard criterion a little later. For now, let us proceed and speculate a bit about what may or may not make physiological sense in

Lesson 2: Linear muscle recruitment .

Lesson 2: Linear muscle recruitment


Let us begin this lesson with a physiological observation. We know that there is a metabolic cost involved in development of muscle force. Food is a limited resource for
living organisms so it is likely that nature has programmed us to save muscle work in some sense. But exactly how?

When two muscles are sharing the load of one joint moment, the options seem to be:

· Letting muscle 1 do the work

· Letting muscle 2 do the work

· Letting the two muscles share the work as we saw in the previous lesson

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 92 of 229

So we can reduce the load on one muscle, but the cost will be more work remaining for the other muscle to do. It seems that a criterion taking both muscles into account is
needed. Let us just briefly recall the formulation of the muscle recruitment problem again:

The simplest imaginable choice of objective function taking the effort of both muscles into account seems to be a linear combination like this:

G=f1/N1+f2/N2

i.e., a linear combination of the two muscle forces, where the N ’s are some choice of normalization factors. Thinking about the physiology we might quickly get the idea
that it is reasonable if strong muscles do more work than weak muscles, so the N ’s could be measures of the strength of each muscle. We are going to stick with that idea
for the remainder of this tutorial because it actually turns out to make sense also experimentally. We can get AnyBody to work with precisely this definition by making the
following additions to our study:

AnyBodyStudy MyStudy = {
AnyFolder &Model = .MyModel;
Gravity = {0.0, -9.81, 0.0};
nStep = 1000; // Lots of time steps to make it run slowly enough

InverseDynamics.Criterion = {
Type = MR_Linear;
};
};

This small addition specifies that the muscles must be recruited as a linear combination. The muscles forces are automatically normalized by the strengths. Running the
analysis and plotting the result as before leaves us with this somewhat surprising result:

It seems that the weaker M2 is slacking around doing nothing and leaving all the work to the stronger M1. It turns out that we always get this type of behavior when
recruiting muscles with a linear objective function. In general, this method will only recruit the minimum number of muscles to balance the system, and the chosen muscles
are those that by combination of their moment arms and strengths are best suited for the purpose. While this might be a reasonable strategy, it is unfortunately totally non-
physiological. It is possible to measure activity in muscles electrically, and these measurements show without a doubt that several muscles spanning the same joint share
the load between them.

This type of muscle recruitment is included in AnyBody for two reasons despite being non-physiological:

1. For completeness. The strategy behind AnyBody is to leave decisions about physiology to the user as much as possible.

2. This type of analysis is excellent for identifying the important muscles in a complex system in a given posture and external load. In complex systems this can be
very challenging to determine manually and the result can be useful for a variety of purposes including decisions on tendon transfer surgery.

For normal purposes, however, the linear criterion is not a good choice, and we shall therefore proceed to investigate another option in

Lesson 3: Quadratic muscle recruitment .

Lesson 3: Quadratic muscle recruitment


The simple example of the previous lesson was enough to show us that linear muscle recruitment is not going to mimic the physiological behavior of living bodies very
well. The next logical step would be to try a quadratic criterion, which we can formulate like this:

Compared with the linear criterion from the previous lesson, a quadratic criterion penalizes large terms in the sum, so it is likely that this would distribute the load between
several muscles rather than recruiting only a minimum number of them.

Quadratic muscle recruitment is often used in the biomechanical literature and many scientists support this method. Its muscle recruitment often agree well with

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 93 of 229

experimental measurements of muscle activity and the resulting joint reaction forces have also been shown in several cases to agree well with experimental data.
Physically, the method is related to well-known concepts such as the root mean square of a series of numbers and also to the field of elasticity. It is a fact that, had the
muscles been purely linear passive-elastic elements capable of pushing as well as pulling, then the force distribution over the muscles would become quadratic, owing to
the fact that the elastic energy stored in a muscle would be a quadratic function of the force it carries.

Before we try it out, let us set up a model that makes more physiological sense than the previous one. Please download and save this zip file and unpack it into some
working directory. Then open AnyBody and load the file Bike2D.main.any. After you have compiled the model into memory you can open up a ModelView window and
see this picture:

This is a simple two-dimensional model of two legs pedaling a bicycle, but it captures many of the complexities of muscle recruitment in real biological systems: closed
kinematic chains, muscle redundancy, changing moment arms, changing force magnitudes and directions.

In the editor window containing Bike2d.main.any, scroll down to the bottom of the file where you find the study section. This study has no particular settings, but a few
additional lines will define a quadratic criterion:

// The study: Operations to be performed on the model


AnyBodyStudy Study = {
AnyFolder &Model = .Model;
Gravity = {0.0, -9.81, 0.0};
tEnd = Main.BikeParameters.T;
nStep = 100;
InverseDynamics.Criterion = {
Type = MR_Quadratic;
UpperBoundOnOff = Off;
};
};

Now reload the model, expand the study tree in the Operation window on the left hand side of the mainframe, pick InverseDynamics by clicking it once and click the Run
button. This should start the analysis and the bicycle starts running the in ModelView window.

After the analysis is completed, click Window->ChartFX to open a window where we can examine graphs. Navigate in the tree on the left hand side of the window through
Study, Output, Model, Leg2D, Right, Mus, and expand the branch for one of the muscles, for instance Ham, which is the hamstring muscle. You will find Activity among
the properties that can be plotted. Select it and then replace the muscle name by an asterisk to simultaneously plot the activities of all the muscles.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 94 of 229

Muscle activity in AnyBody is defined as the f / N property that we minimized as a square sum over all the muscles. In other words, muscle activity is a measure of the
force in a muscle relative to its strength. The resulting graphs show that Several muscles are active simultaneously and that they are active to different degrees as the
movement progresses. If you hold the mouse over each of the curves a little window will pop up and tell you the name of the muscle. The green curve that peaks in the
beginning of the cycle, for instance, is the vasti muscles, i.e. the large muscles on the frontal side of the thigh.

You can also see that the maximum muscle activity is around 0.78, i.e. 78 percent. The advantage of plotting activities is that a given muscle is loaded to its maximum
strength when its activity is 100 percent. This is also called Maximum Voluntary Contraction, or MVC.

So the graphs show that this is a rather strenuous pedaling activity. The reason is obvious if you look further up in the Bike2D.main.any file. Near the top of the file, a
number of parameters are available for the user to set:

// Kinematic parameters
AnyVar Cadence = 60.0; //Cadence in RPM
AnyVar MechOutput = 400; //Average Mechanical output over a cycle in Watt

The mechanical output has been set to 400 W at a cadence of only 60 rpm and this will require most of the strength of the rider.

Try increasing the load to 500 W, reload the model, rerun the analysis, and plot the muscle activities again. Now you should get the following picture:

The recruitment pattern is very similar to the previous one, but the recruitment of the vasti as well as the hamstrings now exceeds 100 percent. This is obviously not
physiologically possible, and muscle recruitment with a quadratic criterion therefore usually has an additional constraint defined, requiring the activation of the muscles not
to exceed 100 percent. We can switch this constraint on by placing double slashes in front of a line in the definition of the quadratic criterion:

// The study: Operations to be performed on the model


AnyBodyStudy Study = {
AnyFolder &Model = .Model;
Gravity = {0.0, -9.81, 0.0};
tEnd = Main.BikeParameters.T;
nStep = 100;
InverseDynamics.Criterion = {
Type = MR_Quadratic;
// UpperBoundOnOff = Off;
};
};

Now, please reload, rerun and replot. The result should be the following:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 95 of 229

This is significantly different from what we had before. The activities beyond 100 percent have been cut off, and the submaximally activated muscles increase their
activation to balance the external load.

The fact that we initially had to explicitly define UpperBoundOnOff = Off shows that the standard setting of the Quadratic is to have the bound on. This makes
physiological sense. The figure right above shows that it is in fact possible for the organism to carry the load without overloading the muscles, so a solution like the
previous one that predicts that the organism cannot carry the load is not satisfactory.

Of course, the organism does have an upper limit to how much load it can carry. Let us investigate what happens when we increase the load further to 800 W:

// Kinematic parameters
AnyVar Cadence = 60.0; //Cadence in RPM
AnyVar MechOutput = 800; //Average Mechanical output over a cycle in Watt

Reloading and rerunning produces this result:

As the model runs, you will receive a warning: “ Overloaded muscle configuration. ” This is AnyBody’s warning that there is no way within the upper bound constraint of
100% muscle activation that the model can recruit the muscles; they are simply not strong enough to carry the external load. AnyBody’s reaction is to change to another
recruitment algorithm that is capable of handling overloaded muscles in the time steps when the Quadratic algorithm cannot handle the case within its bounds. We are
going to return to this algorithm, the MinMax algorithm, in more detail later in this tutorial. For now, it suffices to say that the solution of the MinMax algorithm and the
Qudratic algorithm with upper bounds is the same at the single point where the organism is exactly 100% loaded. The points where the shift between the algorithms take
place are clearly identifiable as the points where the envelope of muscle activation exceeds 1.

It is important to emphasize that muscle activation beyond 1 is not physiological, so it might have made sense for AnyBody not to return a solution at all. But that would
not have been very helpful. It would leave the user with no clue about why the organism is overloaded or how much. The method you see here allows the user to
investigate the problem and make the necessary changes to the model or at least quantify its overloaded.

There are properties of the quadratic algorithm, however, that are somewhat unsatisfactory: While it requires the upper bounds to extract the maximum strength from the
organism, the same upper bounds tend to produce activation curves with kinks that seem to leave a non-physiological impression. It seems like the key to avoiding this
would be to get the muscles to be more synergistic. How that might be done is the topic of

Lesson 4: Polynomial muscle recruitment.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 96 of 229

Lesson 4: Polynomial muscle recruitment


In the previous two lessons, we learned that linear muscle recruitment leads to no muscle synergy at all, while quadratic muscle recruitment seems to result in some
synergy between the muscles. In general, the higher the order of the objective function of our recruitment problem, the more synergy we get between the muscles. This is
due to the fact that higher orders tend to put higher penalization on large values in the sum and hence tend to distribute the load more evenly between the muscles.

So, perhaps if we use a higher order sum of muscle activities we may have less need for the upper bound on the muscle recruitment. AnyBody has a recruitment algorithm
that lets you select your own order of the problem. Let us investigate it a little.

First, let us change the power output of the bicycle model back to a manageable but still challenging level:

// Kinematic parameters
AnyVar Cadence = 60.0; //Cadence in RPM
AnyVar MechOutput = 500; //Average Mechanical output over a cycle in Watt

Then we change the study section to the polynomial option:

// The study: Operations to be performed on the model


AnyBodyStudy Study = {
AnyFolder &Model = .Model;
Gravity = {0.0, -9.81, 0.0};
tEnd = Main.BikeParameters.T;
nStep = 100;
InverseDynamics.Criterion = {
Type = MR_Polynomial;
};
};

Now we have specified polynomial muscle recruitment, which comes down to the following objective function:

We have not, however, specified what the power p is. In the absence of a specification, AnyBody assumes p = 3, i.e. one higher than the quadratic criterion from before.
When we ran the quadratic criterion with 500 W mechanical output, two of the muscle activities became constrained by the upper of 1. If we reload and rerun the model
now, we get the following result:

The muscle activations are nice and smooth and the upper limit on the muscle activity is not active. It is hard to say which criterion is the right one, but it appears that for
this load the third order polynomial criterion is better than the quadratic criterion from before. The third order criterion is in general a good compromise between different
recruitment criteria, and this is why it is the default in AnyBody when the user makes no other specifications.

Of course, everything has a limit, and if we raise the power output a bit more to 650 W:

// Kinematic parameters
AnyVar Cadence = 60.0; //Cadence in RPM
AnyVar MechOutput = 650; //Average Mechanical output over a cycle in Watt

…then we once again will have muscles limited by the upper bound on muscle recruitment:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 97 of 229

The polynomial criterion allows us to select a higher order if we like. It can be done like this:

InverseDynamics.Criterion = {
Type = MR_Polynomial;
Power = 5;
};

which sets the order of the polynomial sum to 5. Reloading and rerunning the model produces this result:

So it would appear that increasing the power of the criterion get the muscles to work more and more together and allow the organism to carry larger loads without
overloading any individual muscle. Of course, at some point of increasing load it will be impossible for a criterion of any order to carry it without overloading the muscles,
and the polynomial criterion reacts to this situation as the quadratic criterion did, i.e. to issue a warning and automatically change to another recruitment criterion that
allows overloaded muscles to give you a visual and quantitative feedback to relate to. Feel free to go ahead and increase the mechanical power of the pedaling to 800 W as
in the quadratic lesson and see how the algorithm reacts.

But why not just use a very high order criterion? It seems that it would extract the maximum strength from the collective organism as we expect the living body to do.

Well, closer inspection of the figure above reveals that the high order criterion comes at a price: Some of the activations and de-activations of the muscles now happen very
quickly and perhaps faster than living muscles can manage. Muscle contraction is an electro-chemical process and it takes some time to develop and release force in a
muscle. The actual time depends somewhat on the circumstances and on the fiber composition in the muscle, but the time is finite and contraction or relaxation cannot
physiologically happen in an instant.

In fact, the power of 5 is the upper limit of the polynomial criterion in AnyBody. This is not only because higher powers cause the muscles to contract and relax very
quickly but also because higher order criteria are potentially less robust and may cause numerical instability in the simulated recruitment.

If it were in fact possible to increase the polynomial power towards infinity, then the muscle recruitment criterion would approach a min/max formulation that, in a
biomechanical context, can be interpreted as a minimum fatigue criterion, and this is not without physiological relevance, so it is the topic of…

Lesson 5: Min/Max recruitment .

Lesson 5: Min/max muscle recruitment

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 98 of 229

With the exception of the linear criterion, each of the options presented in the previous lessons have produced plausible muscle recruitment patterns. We have found that
polynomial criteria of increasing order produce increasing degrees of synergism between the muscles. Maximum synergism would be the case where all muscles capable of
a positive contribution to balancing the external load work together in such a way that the maximum relative load of any muscle in the system is as small as possible. This
would physiologically be a minimum fatigue criterion because fatigue is likely to happen first in the muscle with the maximum relative load, and it makes physiological
sense that the body might work that way. It would mean that the body would maximize its endurance and precisely this criterion might decide survival of the fittest in an
environment where organisms are competing with each other for limited resources.

Mathematically, it turns out that we would get exactly that kind of recruitment if we let the power of the polynomial criterion go to infinity. It would not be numerically
possible to do that with the polynomial algorithm we presented in the previous lesson, so it is necessary to use a dedicated algorithm for that purpose. In its pure form it is
called MinMaxStrict, and we might as well try it out on the bicycle example right away. It is necessary to change just a little bit in the definition of the study:

AnyBodyStudy Study = {
AnyFolder &Model = .Model;
Gravity = {0.0, -9.81, 0.0};
tEnd = Main.BikeParameters.T;
nStep = 100;
InverseDynamics.Criterion = {
Type = MR_MinMaxStrict;
};
};

Reloading and rerunning give us the following result:

When comparing with the muscle activation curves we have seen earlier it looks like there are less muscles represented on this one, but that is not actually the case. It just
looks like there are fewer curves here because a lot of them are exactly on top of each other. This is a logical consequence of minimizing the maximum muscle activity:
when muscles help each other as much as they can, many of them end up with the same activity.

Min/max recruitment leads to a very well-defined envelope of muscle activation, and it plays an important role in a lot of cases of ergonomic design. It is so important, in
fact, that the envelope has its own predefined output variable placed alongside the other global values such in the study:

The variable, MaxMuscleActivity, is interesting because the maximally activated muscle(s) in the problem likely determine the perceived effort. To illustrate this, think of

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 99 of 229

lifting an average size bag. It may not be difficult to do with your hand, but if you were to grab the handle with your little finger only, then you would perceive the lifting of
the bag as rather laborious because its weight would now have to be carried by a much higher maximum muscle activity in much smaller muscles. This means that the
maximum muscle activity is a good measure to use in ergonomic design cases where we want to determine a tool or a posture that minimizes the effort of a given work
task. Rather than having to review a lot of muscle activations in the entire body we can capture the effort in a single curve as shown above.

Closer inspection of the curve above shows that the muscle activation peaks at 88.2%. Near the top of the Bike2D file you find the variable SaddleHeight. As the name
indicates, it determines the height of the saddle of the bike, or more precisely the vertical distance between the crank shaft and the hip joints. The current value is 0.63 m.
Try raising the saddle by 2 cm by the following change:

AnyVar SaddleHeight = 0.65; //Height of hip joint measured vertically from the crank

Then load and run the problem again and plot the MaxMuscleActivity. It now peaks at 83.5% indicating that the higher saddle has made it somewhat easier for the rider to
pedal the bicycle.

Notice that the maximum muscle activity is defined for any type of muscle recruitment, but the min/max muscle recruitment illustrates its definition better because it leads
to such a clear envelope. Furthermore, because min/max recruitment causes the muscle to cooperate as much as possible, the envelope simulated by this criterion is smaller
than or equal to the envelope of any other criterion that can be defined. In terms of maximum muscle activity, the min/max muscle recruitment simply leads to the lowest
possible maximum activation by which the external load can be carried. While this may or may not be the way muscle are recruited in reality, it is a better way of assessing
ergonomics than most of the other criteria we can think of. If we run the bicycle simulation with AnyBody’s standard muscle recruitment (third order polynomial with
upper bounds on activities) for saddle heights of 0.63 m and 0.65 m and plot the two curves of maximum muscle activation, we can get the following:

Notice that because the upper bounds on muscle activation become active, the curves have the same maxima despite the change of saddle height, and the ergonomic
advantage of the higher saddle comes out as a smaller area under the red curve compared to the blue.

The reason why the MinMaxStrict criterion is not the default in AnyBody despite its attractive properties for ergonomic investigations is that it switches muscles in and out
very abruptly when they change moment arms from negative to positive. These sudden shifts may sometimes happen faster than physiologically possible and they also
mean that muscles with just a marginally positive contribution will be activates to their full potential. As we have seen in the previous sections, lower order polynomial
criteria do not have that type of behavior.

It is tempting to think that there might be a compromise between polynomial and the min/max criterion that would have the attractive properties of both strategies, i.e. get
close to the minimum activation or fatigue of the muscle system and also have relatively smooth activation curves. In the next tutorial we shall look at composite criteria
that might combine some of the attractive features of the pure criteria we have investigated so far. This takes place in

Lesson 6: Composite recruitment criteria

Lesson 6: Composite recruitment criteria


So far we have investigated recruitment criteria in the form of polynomial sums with degrees ranging from 1 (linear recruitment) to infinity (min/max recruitment). It is not
given, however, that any single degree criterion is the right one.

It seems reasonable that a high order criterion is correct when the external load approaches the limit of the organism’s strength because that enables the organism to use its
full strength. On the other hand, it might also be unreasonable that a lot of muscles should be activated if the external load is very small and/or some of the muscles have a
very unfavorable moment arm and therefore can contribute very little.

Praagman et al (2003, 2006) reviewed the physiological mechanisms behind muscle contraction and concluded that there are two energy-consuming processes, namely
detachment of cross bridges and re-uptake of calcium. If muscle recruitment is based on minimization of energy, then it is reasonable to think that the objective function
contains a contribution from both these processes and they turn out to be represented by an objective function with a linear as well as a quadratic term. To investigate this,
let us change the muscle recruitment to the type of quadratic criterion that also accepts a linear term:

// The study: Operations to be performed on the model


AnyBodyStudy Study = {
AnyFolder &Model = .Model;
Gravity = {0.0, -9.81, 0.0};
tEnd = Main.BikeParameters.T;
nStep = 100;
InverseDynamics.Criterion = {
Type = MR_QuadraticAux;
AuxLinearTerm.Weight = 0.0;
};
};

…and let us also reduce the power consumption to a level that does not require upper limits on the muscle activation:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 100 of 229

// Kinematic parameters
AnyVar Cadence = 60.0; //Cadence in RPM
AnyVar MechOutput = 250; //Average Mechanical output over a cycle in Watt

Loading and running this version will produce the exact same result as the standard quadratic criterion because the weight on the linear term is set to zero. The result looks
like this:

However, if we add a bit of weight to the linear term:

InverseDynamics.Criterion = {
Type = MR_QuadraticAux;
AuxLinearTerm.Weight = 0.1;
};
};

…we can influence the resulting recruitment and get the following result:

The muscle synergy is slightly reduced by the linear term in the objective function, and the maximum muscle activation is consequently slightly higher. Is this better than
the pure quadratic recruitment? That is difficult to answer, but the option allows a discerning user to influence the recruitment criterion and to build in physiological
considerations such as those by Praagman et al.

The min/max muscle recruitment has a similar alternative form that allows for the addition of a linear or quadratic term to the objective function. In this case the quadratic
term turns out to be the more interesting, and it does in fact allow for a recruitment behavior that combines some of the good features of quadratic and min/max
recruitments. To investigate this in more detail, let us first take a look at the optimization problem that is solved in the min/max muscle recruitment problem. We
mentioned before that min/max can be interpreted as a polynomial criterion for which the power is going to infinity. Obviously, the solution of an infinity-powered
objective function requires some additional mathematical tricks. The trick is to redefine the muscle recruitment problem to the following form:

Minimize

Subject to

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 101 of 229

It is easy to see why this minimizes the maximum muscle activity: The only way to reduce the objective function, β , and to honor the constraints is to simultaneously
reduce all the muscle activities. The question now is: what happens if we add a quadratic auxiliary term to the objective function, β , this way:

Minimize

Subject to

where ε is the weight we use to tune the influence of the quadratic term.

We can do this in AnyBody by choosing the auxiliary form of the min/max recruitment criterion:

AnyBodyStudy Study = {
InverseDynamics.Criterion = {
Type = MR_MinMaxAux;
AuxQuadraticTerm.Weight = 1;
};

Reloading and rerunning produces the following rather attractive result:

This appears to produce a combination of soft onset and offset of muscles together with a clearly defined envelope on which several muscles cooperate evenly to carry the
load. Please notice, however, that the effect of the Weight property, i.e. the ε in the objective function, is somewhat problem dependent because the size of the sum that it
multiplies depends on the number of muscles in the system while the size of the β variable remains between 0 and 1 for normal problems. So models with many muscles
would typically require a smaller value of ε .

From what we have seen so far, the MinMaxAux criterion looks ideal from a mathematical and physiological point-of-view. Unfortunately, there is one additional,
physiological requirement that we have not touched upon, and on the MinMaxAux criterion fails on that. To understand it, let us make a thought experiment:

1. We create a model of a person lifting a box. The mass of the box is 10 kg. The muscle recruitment algorithm will return some distribution of load between the
muscles in the system.

2. Then we change the mass of the box to 5 kg and run the model again. This gives us a different muscle recruitment pattern. Probably the muscles would now be
somewhat less loaded than before.

3. Now we create a model with two people in it. This is entirely possible to do in AnyBody. The two human models are exactly the same as before and one is lifting a
10 kg box, and the other is lifting a 5 kg box. Since the two body models are completely independent from each other, except from the fact that they are present in the same
computer model, we would expect the muscle recruitment we get when they are inside a single model to be exactly the same as we got for the two single-body models we
had before. And this would be the case with the polynomial criteria of any degree and with the MinMaxStrict criterion, but it would not be the case with the MinMaxAux
criterion, and this does not seem to be right.

So the conclusion is that the MinMaxAux criterion, despite its attractive features, should be used with care in models where there is a chance that some model parts are
independent of each other.

Let us carry on with Lesson 7: Calibration

References
Praagman, M., Veeger, H.E.J., Chadwick, E.K., Colier, W.N., van der Helm, F.C. (2003). Muscle oxygen consumption, determined by NIRS, in relation to external force

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 102 of 229

and EMG. Journal of Biomechancis, 36, 905–912.

Praagman M, Chadwick EKJ, van der Helm FCT, Veeger HEJ (2006): The relationship between two different mechanical cost functions and muscle oxygen consumption.
Journal of Biomechanics, 39, 758–765.

Lesson 7: Calibration
One of the challenges in body modeling is that models must be able to change size to reflect individuals of different statures. Even if you are working on a model of a
particular individual, you will almost always want to change the dimensions of the model as you are building it. And if you are developing a generic model to represent a
range of body proportions, you are likely to want the model to depend on the anthropometrical parameters you define. For instance, the weight of a segment is often
represented as some fraction of the full body weight. Such a property you could make parametric by simply defining it as a function of the full body weight by means of a
simple formula.

But other dimensions are more subtle and difficult to establish as a direct functional dependency of other parameters. Tendon lengths are perhaps the most prominent
example. If you are in doubt of the importance of tendon lengths, just try to bend over and touch your toes with your knees stretched. Some of us have hamstring tendons
that are so short that we can hardly reach beyond our knees, so tendon lengths directly limit our ranges of motion. But they also influence the working conditions of our
muscles even when the muscle-tendon unit is not stretched to its limit, so it is important that we define the muscle tendon unit so that it fits the body model.

A muscle-tendon unit is attached to at least two segments at its origin and insertion respectively. To make things worse, some muscles span several joints, and most
muscles wrap over bones and other tissues with complex geometries on their way from origin to insertion. So, the basic idea behind calibration of tendon lengths in
AnyBody is the assumption that each muscle-tendon unit has its optimal length at some particular position of the joints it spans. We simply define one or several studies
that put the body model in these positions and adjust the lengths of the tendons to give the attached muscles their optimal lengths in those positions. When you
subsequently run an analysis, the system uses the calibrated tendon lengths regardless of how they are defined in the AnyScript file. (This means that you have to run the
calibration(s) every time you have reloaded the model if they are to take effect).

AnyBody has several different types of muscle models. Some are very simple and contain no strength-length relationship, while others do. It goes almost without saying
that the former type is not affected by calibration. If you use one of the latter - more advanced - models, however, calibration may be crucial. If the tendon is too long, the
muscle will end up working in an unnaturally contracted state where it has very little strength. If the tendon is too short, the muscle will be stretched, and its passive
elasticity will affect the force balance in the system. Since the passive elastic force in a muscle-tendon unit typically grows very rapidly with stretching, a too short tendon
can cause very large antagonistic muscle actions.

Enough talk! Let's define a muscle and calibrate it. We shall begin with the simple arm model we developed in the " Getting Started with AnyScript " tutorial. If you have
not already saved the model in a file, get it here: arm2d.any .

In that simple example, all the muscles were assumed to be of a simple type with constant strength. We shall add another and much more detailed muscle model:

// -----------------------------------------------------
// Muscles
// -----------------------------------------------------
AnyFolder Muscles = {
//---------------------------------
// We define one simple muscle model, which we will use
// for all muscles except biceps long
AnyMuscleModel MusMdl = {
F0 = 300;
};
AnyMuscleModel3E BicepsLongModel = {
AnyVar PCSA = 2.66; // Physiological cross sectional area [cm^2]
F0 = PCSA*30; // Presuming a maximum muscle stress of 30 N/cm^2
Lfbar = 0.123; //Optimum fiber length [m]
Lt0 = 0.26; //First guess of tendon slack length [m]
Gammabar = 0.3*(pi/180); //Pennation angle converted to radians
Epsilonbar = 0.053; //Tendon strain at F0
K1 = 10; //Slow twitch factor
K2 = 0; //Fast twitch factor(zero when no info available)
Fcfast = 0.4; //Percentage of fast to slow factor
Jt = 3.0; //Shape parameter for the tendon stiffness
Jpe = 3.0; //Shape parameter for the parallel stiffness
PEFactor = 5.0; //Parameter for influence of parallel stiffness
}; // End of BicepsLongModel
};

As you can see from the comments, the muscle has many parameters you have to set. The significance of each of these is explained in detail in the muscle modeling
tutorial . For this model to take effect, we must assign it to the biceps long muscle. It is a little further down in the file, where the red line must be changed:

//---------------------------------
AnyViaPointMuscle BicepsLong = {
AnyMuscleModel &MusMdl = .BicepsLongModel;
AnyRefNode &Org = Main.ArmModel.GlobalRef.BicepsLong;
AnyRefNode &Ins = ..Segs.LowerArm.Biceps;
AnyDrawViaPointMuscle DrwMus = {};
};

What we have done here is to give BicepsLong a new and more advanced muscle model. In this lesson, we also switch to a different muscle recruitment criteria
MR_MinMaxStrict, which is better suited for InverseDynamics of overloaded models:

AnyBodyStudy ArmStudy = {
AnyFolder &Model = .ArmModel;
InverseDynamics.Criterion.Type = MR_MinMaxStrict;
Gravity = {0.0, -9.81, 0.0};
};

Let's have a look at the consequences. Press the M<-S button or F7 and subsequently run the InverseDynamics. Then, open a new ChartFX window to investigate the
results.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 103 of 229

This graph shows the muscle force or more precisely the force in the tendon. The force in this more complex muscle model is composed of two elements: The active part
coming from the contractile element of the muscle, and the passive part due to the stretching of the parallel-elastic part of the muscle. The two parts come together in the
tendon force, Ft. The parallel-elastic part of the muscle is represented by Fp in the result tree. If you pick this property, you should get the following graph:

The parallel-elastic force sets in when the muscle is stretched beyond its optimal fiber length. In the movement of this example, the elbow starts at 90 degrees flexion, and
as the graph shows, this gives rise to about 10 N of passive force at the beginning of the movement. This indicates that the tendon we have specified is too short. If the
movement was extending the elbow instead of flexing it, the passive force would rise sharply. This means that the result of the simulation depends a lot on having the
correct length of the tendon. If it is too short, too much of the load will carried by passive muscle forces. In this example where we have only one muscle with a complex
model, it would not be too difficult to adjust the tendon length manually until we get it right, but in models with many muscles, this can be a very tedious task, particularly
since it has to be repeated every time the dimensions of the model are changed. Instead, the answer is to let AnyBody calibrate the tendon length automatically.

AnyBody's advanced muscle model, the AnyMuscleModel3E, is basically a phenomenological model based on the classical works of Hill. It presumes that each muscle has
an optimum contraction in which its fibers have their best force-producing capability. If we knew the set of joint positions corresponding to this optimum fiber length for
each muscle, then those joint positions were the ones we would be calibrating the muscle in.

Finding joint positions corresponding to optimum muscle fiber lengths is an active and rather young area of research, and the correct values are only known for a few
muscles in the body. However, it is not surprising that we seem to have been built in such a way that our muscles attain their optimum fiber lengths in the joint positions
where they do most of their work, and if you are unable to find the information about optimum joint positions you need, then your best choice may be to calibrate the
muscle in the joint position where it primarily works.

Calibrating the muscle in a particular position requires a calibration study. Its basic definition is very simple:

// =======================================================
// "The body study"
// =======================================================
AnyBodyStudy ArmModelStudy = {
AnyFolder &Model = Main.ArmModel;
InverseDynamics.Criterion.Typer = MR_MinMaxStrict;
Gravity = {0.0, -9.81, 0.0};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 104 of 229

};
// A new calibration study
AnyBodyCalibrationStudy CalibrationStudy = {
AnyFolder &Model = Main.ArmModel;
nStep = 1;
}; // End of study

If you load the model in you can study the structure of the new study:

You can see that it has multiple operations. The interesting ones are the two latter: TendonLengthAdjustment and LigamentLengthAdjustment. As the names indicate they
are for tendon and ligament calibration respectively. Notice that the study only has one time step. The model posture in that step should be the position in which you wish
to calibrate the tendon. If you run the TendonLengthAdjustment operation you will notice that the model takes the initial posture of the flexion movement it was doing in
the InverseDynamics. This is because of the line

AnyFolder &Model = Main.ArmModel;

The ArmModel contains movement drivers, and when they are included in the study they cause the model to attain the same posture in the calibration study as it does in the
inverse dynamic analysis. To be able to calibrate in another posture we must perform a small restructuring of the model and perhaps recommend a organizing things a little
differently in general when making models.

We included the movement in the model when we developed it in the " Getting Started with AnyScript " tutorial because we wanted things to be simple. But think for a
moment about how you would typically want to use models. Let's imagine you have developed a model of a leg. One day you might want to simulate squat, another day
perhaps gait, and yet another day a football kick. You would want to use the same model but with different sets of drivers. This speaks in favor of having drivers, loads,
and other problem-specific properties outside the folder containing the body model.

Calibration is actually an example of using the same model with two different movements, so we have to place the drivers outside the ArmModel folder. In the editor,
highlight the entire Drivers folder, cut it out, and paste it in right below the end of the ArmModel folder like this:

}; // ArmModel

AnyFolder Drivers = {

//---------------------------------
AnyKinEqSimpleDriver ShoulderMotion = {
AnyRevoluteJoint &Jnt = Main.ArmModel.Jnts.Shoulder; // Changed!
DriverPos = {-100*pi/180};
DriverVel = {30*pi/180};
Reaction.Type = {Off};
}; // Shoulder driver

//---------------------------------
AnyKinEqSimpleDriver ElbowMotion = {
AnyRevoluteJoint &Jnt = Main.ArmModel.Jnts.Elbow; // Changed!
DriverPos = {90*pi/180};
DriverVel = {45*pi/180};
Reaction.Type = {Off};
}; // Elbow driver
}; // Driver folder

Notice that after moving the Drivers folder we have changed the references to the joints. We also have to change the study a little bit. This is because the study points at the
ArmModel folder, and that no longer contains a movement, so the study would not know how to move the model, unless we add this line:

// =======================================================
// "The body study"
// =======================================================
AnyBodyStudy ArmStudy = {
AnyFolder &Model = .ArmModel;
AnyFolder &Drivers = .Drivers;
InverseDynamics.Criterion.Type = MR_MinMaxStrict;
Gravity = {0.0, -9.81, 0.0};
};

Now we are ready to define a couple of static drivers specifically for calibration of the muscles. We create a CalibrationDrivers folder right below the Drivers folder:

// -----------------------------------------------------
// Calibration Drivers
// -----------------------------------------------------
AnyFolder CalibrationDrivers = {
//---------------------------------
AnyKinEqSimpleDriver ShoulderMotion = {
AnyJoint &Jnt = Main.ArmModel.Jnts.Shoulder;
DriverPos = {-90*pi/180}; // Vertical upper arm
DriverVel = {0.0};
Reaction.Type = {Off};
};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 105 of 229

//---------------------------------
AnyKinEqSimpleDriver ElbowMotion = {
AnyJoint &Jnt = Main.ArmModel.Jnts.Elbow;
DriverPos = {30*pi/180}; // 20 degrees elbow flexion
DriverVel = {0.0};
Reaction.Type = {Off};
};
};

These drivers are static because their velocities are zero. They specify a posture with the upper arm vertical and the elbow at 30 degrees flexion. Notice the expressions
converting degrees to radians.

The final step is to modify the calibration study to use the calibration drivers:

// A new calibration study


AnyBodyCalibrationStudy CalibrationStudy = {
AnyFolder &Model = Main.ArmModel;
AnyFolder &Drivers = .CalibrationDrivers;
nStep = 1;
}; // End of study

What we have now is a study that uses the model together with two static drivers for calibration of the muscles, and a study that uses the model with the previous set of
dynamic drivers. If you run the CalibrationStudy first, the system will adjust the tendon lengths and remember the values for the subsequent run of the AnyBodyStudy.
Running this sequence of two studies reveals that there is no more passive force present in the BicepsLong muscle because it has now been calibrated in a more natural
position.

The final issue of this tutorial is: How can we handle calibration of different muscles in different positions? For instance, it might be reasonable to believe that the elbow
extensors should be calibrated in a different elbow position than the elbow flexors. How can we accomplish that? Well a closer investigation of the calibration study listed
above can actually give us a clue. The study contains the following two lines:

AnyFolder &Model = Main.ArmModel;


AnyFolder &Drivers = Main.CalibrationDrivers;

This tells us that a study manipulates the objects mentioned inside the study folder, in this case the ArmModel and the CalibrationDrivers. Perhaps you remember that we
took the drivers out of the ArmModel, so that we could refer separately to them in the study? We did this to be able to not refer to the movement drivers when we run the
calibration study and vice versa. Similarly, if we want to calibrate a subset of the muscles, we simply make it possible to just refer to precisely this subset in the study and
leave the others out.

Let us create a new muscle model for TricepsLong and calibrate that in another position.

}; // End of BicepsLongModel
AnyMuscleModel3E TricepsLongModel = {
AnyVar PCSA = 15; // Physiological cross sectional area [cm^2]
F0= PCSA*30; // Presuming a maximum muscle stress of 30 N/cm^2
Lfbar= 0.194; //Optimum fiber length [m]
Lt0 = 0.35; //First guess of tendon slack length [m]
Gammabar = 2.0*(pi/180); //Pennation angle converted to radians
Epsilonbar = 0.053; //Tendon strain at F0
K1 = 10.0; //Slow twitch factor
K2 = 0.0; //Fast twitch factor(zero when no info available)
Fcfast = 0.4; //Percentage of fast to slow factor
Jt = 3.0; //Shape parameter for the tendon stiffness
Jpe = 3.0; //Shape parameter for the parallel stiffness
PEFactor = 5.0; //Parameter for influence of parallel stiffness
}; // End of TricepsLongModel

AnyViaPointMuscle TricepsLong = {
AnyMuscleModel &MusMdl = .TricepsLongModel;
AnyRefNode &Org = ..GlobalRef.TricpesLong;
AnyRefNode &Ins = ..Segs.ForeArmArm.Tricpes;
AnyDrawViaPointMuscle DrwMus = {};
};

Once again we need two drivers to put the model into the posture for calibration of the TricepsLong muscle:

// -----------------------------------------------------
// Triceps Calibration Drivers
// -----------------------------------------------------
AnyFolder TricepsCalibrationDrivers = {
//---------------------------------
AnyKinEqSimpleDriver ShoulderMotion = {
AnyJoint &Jnt = Main.ArmModel.Jnts.Shoulder;
DriverPos = {-90*pi/180}; // Vertical upper arm
DriverVel = {0.0};
Reaction.Type = {Off};
};
//---------------------------------
AnyKinEqSimpleDriver ElbowMotion = {
AnyJoint &Jnt = Main.ArmModel.Jnts.Elbow;
DriverPos = {90*pi/180}; // 30 degrees elbow flexion
DriverVel = {0.0};
Reaction.Type = {Off};
};
};

As you can see, this differs from the drivers for calibration of BicepsLong only by using 90 degrees elbow flexion rather than 30 degrees.

What we could do now is to take the two advanced muscle models out of the ArmModel folder, so that we could refer to them individually in the study; just like we did
with the drivers. But let's try something else instead. We'll simply refer directly to the individual elements of the ArmModel in the calibration study rather than the entire

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 106 of 229

ArmModel. This way we are able to leave out the muscles we do not want to include. So we simply make a new study that looks like this:

// A calibration study for TricepsLong


AnyBodyCalibrationStudy TricepsCalibrationStudy = {
AnyFixedRefFrame &GlobalRef = Main.ArmModel.GlobalRef;
AnyFolder &Segs = Main.ArmModel.Segs;
AnyFolder &Jnts = Main.ArmModel.Jnts;
AnyViaPointMuscle &TricepsLong = Main.ArmModel.Muscles.TricepsLong;
AnyFolder& Drivers = Main.TricepsCalibrationDrivers;
nStep = 1;
}; // End of study

Notice that this study refers to each folder inside the ArmModel individually. This way, we can restrict our references only to the TricepsLong muscle and leave all the
other muscles out. This means that the other muscles will not be affected by this calibration. So if you initially calibrate all the muscles by the CalibrationStudy and
subsequently run the TricepsCalibrationStudy, then the latter will not overwrite the effect of the former, but only for the muscle mentioned in the study, i.e. the
TricepsLong.

Here's a link to the finished calibration.any example.

Muscle modeling

Muscles are the actuators of living bodies. They are activated by the central nervous system (CNS) by a complicated electro-chemical process. Determining the activation
that realizes a desired movement requires an extremely intricate control algorithm. The CNS is superior to any computer man has made in this respect. AnyBody mimics
the workings of the CNS by computing backwards from the movement and load specified by the user to the necessary muscle forces in a process known as inverse
dynamics. To do so, the system must know the properties of the muscles involved, and this is where muscle modeling comes into the picture.

AnyBody contains three different muscle models ranging from simple to more complicated physiological behavior. The simplest model just assumes a constant strength of
the muscle regardless of its working conditions. The more complicated models take such conditions as current length, contraction velocity, fiber length, pennation angle,
tendon elasticity, and stiffness of passive tissues into account. Please refer to the AnyScript Reference manual (Find it in AnyBody->Help of the online version ) for
concise information about the available muscle models:

1. AnyMuscleModel - assuming constant strength of the muscle


2. AnyMuscleModel3E - a three element model taking serial and parallel elastic elements into account along with fiber length and contraction velocity
3. AnyMuscleModel2ELin - a bilinear model taking length and contraction velocity into account.

The muscle models can be linked to different types of muscles:

1. AnyViaPointMuscle - a muscle that passes through any number of nodes on segments on its way from origin to insertion
2. AnyShortestPathMuscle - a muscle that can wrap over geometries such as cylinders and ellipsoids and even CAD-defined surfaces. Please beware that this muscle
type is very computationally demanding and requires careful adjustment.
3. AnyGeneralMuscle - a more standard actuator-type muscle that can be attached to a kinematic measure.

Please refer to the AnyScript Reference for more information, or proceed to the basics of muscle modeling in Lesson 1 .

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 107 of 229

Lesson 1: The basics of muscle definition


The key to understanding muscles in the AnyBody Modeling System is to realize that they mechanically consist of two separate computational models:

1. The kinematic model, which determines the muscle's path from origin to insertion depending on the posture of the body. This also entails finding the length and
contraction velocity of the muscle.
2. The strength model which determines the muscle's strength and possible its passive elastic force depending on the kinematic state of the muscle.

This would be a sad excuse for a tutorial if we did not have an example to work on. So lt us quickly construct a very simple example that will enable us to examine the
properties of muscles. Here's an extremely simple one-degree-of-freedom model (right-click and save to disk) :

// This is a very simple model for demonstration of muscle modeling


Main = {

AnyFolder MyModel = {

// Global Reference Frame


AnyFixedRefFrame GlobalRef = {
AnyDrawRefFrame drw = {
RGB = {1,0,0};
};
}; // Global reference frame

// Define one simple segment


AnySeg Arm = {
r0 = {0.500000, 0.000000, 0.000000};
Mass = 1.000000;
Jii = {0.100000, 1.000000, 1.000000}*0.1;
AnyRefNode Jnt = {
sRel = {-0.5, 0.0, 0};
};
AnyDrawSeg drw = {};
};

// Attach the segment to ground by a revolute joint


AnyRevoluteJoint Jnt = {
AnyRefFrame &ref1 = .GlobalRef;
AnyRefFrame &ref2 = .Arm.Jnt;
Axis = z;
};

// Drive the revolute joint at constant velocity


AnyKinEqSimpleDriver Drv = {
DriverPos = {-10*pi/180};
DriverVel = {40*pi/180};
AnyRevoluteJoint &Jnt = .Jnt;
Reaction.Type = {0};
};

}; // MyModel

// The study: Operations to be performed on the model


AnyBodyStudy MyStudy = {
AnyFolder &Model = .MyModel;
InverseDynamics.Criterion.Type = MR_MinMaxStrict;
Gravity = {0.0, -9.81, 0.0};
};
}; // Main

When you load the model, open a model view window, and run the SetInitialConditions operation, you should get the following picture:

The model has a driver, so you can run the kinematic analysis and see the movement. The arm flexes about the origin of the red reference frame. If you try to run the
InverseDynamicAnalysis, you will get an error:

ERROR: Muscle recruitment analysis failed, simplex solver reports that solution does not satisfy all constraints.

This is because the model does not have any muscles to balance the arm against the downward pull of gravity. Let us define the simplest possible muscle to carry the load.
As mentioned above, a muscle has two basic components: a kinematic model, and a strength model. We shall begin with the latter, and for the time being define the
simplest possible version.

If you pick the Classes tab in the tree view on the left hand side of the Editor Window, then you will get access to the class tree. Expand the tree as shown in the picture
until you get to the AnyMuscleModel.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 108 of 229

Notice that this class has three derived classes. These are more advanced muscle models, and we shall get to those later. However for the time being, place the cursor in the
Editor View on an empty line just after the end brace of the driver definition, right-click the AnyMuscleModel class in the tree, and select "Insert Class Template".This
causes an instance of the AnyMuscleModel class to be inserted into the model (new code marked with red):

// Drive the revolute joint at constant velocity


AnyKinEqSimpleDriver Drv = {
DriverPos = {-10*pi/180};
DriverVel = {40*pi/180};
AnyRevoluteJoint &Jnt = .Jnt;
Reaction.Type = {0};
};

AnyMuscleModel <ObjectName> = {
F0 = 0;
};

This is the simplest type of muscle model the system provides, and it is simply a specification of strength corresponding to the assumed maximum voluntary contraction of
the muscle. A muscle with this type of model does not have any dependency on length or contraction velocity, and it does not take the passive elasticity of the tissue into
account. Despite this simplicity, it is used with considerable success for many studies where the movements or postures are within the normal range of the involved joints,
and where contraction velocities are small.

Let us perform the necessary modifications to make the model useful to us:

AnyMuscleModel SimpleModel = {
F0 = 100;
};

The next step is to define a muscle that can use the model. This is actually the first of the two elements mentioned above: Muscle kinematics.

Again, the AnyBody Modeling System provides a number of choices, and we shall start by picking the simplest one. It is instructive to once again use the tree to insert a
template of the muscle object, because the tree reveals the class dependency. A muscle resolves kinematical information in the sense that it has a certain path from origin to
insertion, and it also provides force. These two properties are reflected in the way the muscle classes are derived from a kinematic measure as well as force classes.

The simplest type of muscle is the AnyViaPoint muscle. It spans the path between origin and insertion by passing through any number of via points on the way. The via
points are fixed to segments or to the global reference frame. It is a simple and convenient way to define many of the simpler muscles of the body, primarily those in the
extremities and the spine. You can, in fact, make a pretty decent model of the legs entirely with via point muscles.

Place the cursor right after the end brace of the musle model, right-click the AnyViaPointMuscle class in the tree, and insert an instance of it:

AnyMuscleModel SimpleModel = {
F0 = 100;
};

AnyViaPointMuscle <ObjectName> = {
AnyMuscleModel &<Insert name0> = <Insert object reference (or full object definition)>;
AnyRefFrame &<Insert name0> = <Insert object reference (or full object definition)>;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 109 of 229

AnyRefFrame &<Insert name1> = <Insert object reference (or full object definition)>;
//AnyRefFrame &<Insert name2> = <Insert object reference (or full object definition)>;
};

Let us start by filling out what we can and removing what we have no use for:

AnyViaPointMuscle Muscle1 = {
AnyMuscleModel &Model = .SimpleModel;
AnyRefFrame &<Insert name0> = <Insert object reference (or full object definition)>;
AnyRefFrame &<Insert name1> = <Insert object reference (or full object definition)>;
};

Notice that we have left only two points in the list of via points. This is obviously the minimal requirement and will create a muscle in a single line from origin to insertion.
But before we proceed with the definition of the muscle we must define the necessary points on the model to attach the muscle to. We shall define the origin on the global
reference frame and the insertion on the segment:

// Global Reference Frame


AnyFixedRefFrame GlobalRef = {
AnyDrawRefFrame drw = {
RGB = {1,0,0};
};
AnyRefNode M1Origin = {
sRel = {0.0, 0.1, 0};
};
}; // Global reference frame
// Define one simple segment
AnySeg Arm = {
r = {0.500000, 0.000000, 0.000000};
Mass = 1.000000;
Jii = {0.100000, 1.000000, 1.000000}*0.1;
AnyRefNode Jnt = {
sRel = {-0.5, 0.0, 0};
};
AnyRefNode M1Insertion = {
sRel = {0.0, 0.1, 0};
};
AnyDrawSeg drw = {};
};

With these two points, we can complete the definition of the muscle:

AnyViaPointMuscle Muscle1 = {
AnyMuscleModel &Model = .SimpleModel;
AnyRefFrame &Orig = .GlobalRef.M1Origin;
AnyRefFrame &Ins = .Arm.M1Insertion;
AnyDrawMuscle drw = {};
};

Notice that we have added an AnyDrawMuscle object to the definition. Like other classes in AnyScript, muscles are not drawn in the model view window unless you
specifically ask for it. When you load the model and run the SetInitialConditions study you will get the following picture (if your model does not load, and you cannot find
the error, click here to download a model that works ):

Notice that the muscle is now able to balance the gravity, and we are able to run the InverseDynamicAnalysis. If you try it out and subsequently open a chart view, you are
able to plot the muscle force:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 110 of 229

The muscle force is the item Fm in the list of properties you can plot for a muscle. As you can see, lots of other properties are available, but if you try to plot them you will
find that many of them are zero. This is because they are not relevant for this very simple type of muscle. We shall return to the significance of the different properties later
in this tutorial.

For now, let's proceed to the next lesson to learn how to control the way a muscle is displayed.

Lesson 2: Controlling muscle drawing


Muscles can be displayed in a variety of fashions depending on the specifications in the AnyDrawMuscle object. Let us take a look at its definition again:

AnyDrawMuscle drw = {};

It obviously does not contain much, so every setting is at its default value leading to the following display of the muscle:

Let us play around with the settings a bit. An easy way to display all the settings is to discard our manually defined AnyDrawMuscle object and insert a template from the
class tree instead:

Erase the previous AnyDrawMuscle, right-click the AnyDrawMuscle in the tree view, an insert an instance:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 111 of 229

AnyViaPointMuscle Muscle1 = {
AnyMuscleModel &Model = .SimpleModel;
AnyRefFrame &Orig = .GlobalRef.M1Origin;
AnyRefFrame &Ins = .Arm.M1Insertion;
AnyDrawMuscle drw = {
//RGB = {0.554688, 0.101563, 0.117188};
//Opacity = 1.000000;
//DrawOnOff = 1.000000;
//Bulging = 0.000000;
//ColorScale = 0.000000;
//RGBColorScale = {0.957031, 0.785156, 0.785156};
//MaxStress = 250000.000000;
};
};

Notice that the <ObjectName> must be manually changed to drw (or any other sensible name). The commented lines (with // in front) are the optional settings. Un-
commenting them will not change much because the values they have listed are the default settings. So we need to change some of the values.

The first thing we shall try is to make the muscle bulge. We do this by setting the value of the Bulge variable to 1. What this transates to is to make the muscle bulging
proportional to the force in the muscle:

AnyDrawMuscle drw = {
//RGB = {0.554688, 0.101563, 0.117188};
//Opacity = 1.000000;
//DrawOnOff = 1.000000;
Bulging = 1;
//ColorScale = 0.000000;
//RGBColorScale = {0.957031, 0.785156, 0.785156};
//MaxStress = 250000.000000;
};

When you try this, you will find that the muscle has become thinner, but you really cannot see it bulge much. The problem is that the thickness of the muscle is scaled by
another factor in addition to the force. This enables the system to create nice visualizations for intensive and light exercises alike. The additional factor is the variable
MaxStress. The following will increase the muscle thickness:

AnyDrawMuscle drw = {
//RGB = {0.554688, 0.101563, 0.117188};
//Opacity = 1.000000;
//DrawOnOff = 1.000000;
Bulging = 1;
//ColorScale = 0.000000;
//RGBColorScale = {0.957031, 0.785156, 0.785156};
MaxStress = 2500;
};

Why does a smaller value of MaxStress lead to a thicker muscle? Well, you can think of the force in a muscle as being the product of a tissue stress and the cross sectional
area. So, the smaller the tissue stress, the larger the cross sectional area for a given force. Thus, reducing the value of MaxStress increases the muscle thickness. If you
reload and run the inverse dynamic analysis you will see that the muscle now has a significant thickness. Its thickness does not change much over the movement, though.
This is because the muscle force is nearly constant over time for the problem we have defined. If we let the joint flex a bit more, then the moment arm of the muscle will
become progressively smaller, and we will get a larger muscle force. The easy way to accomplish this is to increase the angular velocity of the joint driver:

// Drive the revolute joint at constant velocity


AnyKinEqSimpleDriver Drv = {
DriverPos = {-10*pi/180};
DriverVel = {80*pi/180};
AnyRevoluteJoint &Jnt = .Jnt;
Reaction.Type = {0};
};

Reload the model and run the InverseDynamicAnalysis operation again. You will see that the arm now flexes up to an almost vertical position. If you plot the muscle force,
Fm, again in a chart view, then you can see how the muscle force goes up drastically with the reduced moment arm:

Consequently the muscle now bulges more towards the end of the movement than it does in the beginning:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 112 of 229

The muscle thickness does not have to reflect force. Choosing other values for the Bulging property will give other results:

Bulging value Effect Comment


0 No bulging This is the default value
1 Muscle force Thickness is proportional to force
2 Muscle strength Constant in this case (but relevant for more advanced muscle models)
3 Muscle activity The ratio between muscle force and muscle strength
4 Constant volume The muscle gets thicker when it contracts

Muscle state can also be visualized with color. This allows for using bulging to visualize the force, while, for instance, muscle activity can be visualized with color. Try the
following:

AnyDrawMuscle drw = {
//RGB = {0.554688, 0.101563, 0.117188};
//Opacity = 1.000000;
//DrawOnOff = 1.000000;
Bulging = 1;
ColorScale = 1;
//RGBColorScale = {0.957031, 0.785156, 0.785156};
MaxStress = 2500;
};

When you reload and run the InverseDynamicAnalysis, you will notice that the red shade of the muscle changes as its activity grows:

When the activity is zero, the color defaults to a rather pale red. You can control this "initial" value of the scaled color through the property RGBColorscale. As the activity
grows towards 1, the color approaches the default value of the muscle given in the RGB property. For instance, if you want the color interpolated from a cold blue to a
warm red as the muscle activity increases, you can use the following settings:

AnyDrawMuscle drw = {
RGB = {1, 0, 0}; //Red
//Opacity = 1.000000;
//DrawOnOff = 1.000000;
Bulging = 1;
ColorScale = 1;
RGBColorScale = {0, 0, 1}; //Blue
MaxStress = 2500;
};

Finally, the muscle drawing object has a couple of properties in common with other drawing objects: You can control the transparency of the object through the property of
that name. Opacity = 1 means opaque, and with Opacity = 0, the object becomes completely invisible. All values in between causes the object to be semi-transparent. You
can also turn of the display of the object entirely off by setting DrawOnOff = 0;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 113 of 229

With the drawing of muscles under control, let us proceed to another important issue. Lesson 3: Via point muscles .

Lesson 3: Via point muscles


Although the name of the muscle class we have used to far is AnyViaPointMuscle, the example has only showed the muscle passing in a straight line between two points.
Real muscles in the body rarely do so. They are usually constrained by various obstacles on their way from origin to insertion, either by connective tissues or by the contact
with bone surfaces.

In the former case, the muscle tends to pass as a piecewise straight line between the constrained points, and this is relatively easy to to accomplish by means of an
AnyViaPointMuscle. In the latter case, the muscle may engage and release contact with the bone surfaces it encounters. This wrapping over bones is a problem of contact
mechanics and optimization. It requires a different muscle class and it is computationally much more demanding. In this lesson we shall look at AnyViaPointMuscles and
postpone the discussion of wrapping to the next lesson.

Anatomically, via point muscles are mostly found in the lower extremities and in the spine, while the arms and shoulders almost exclusively have wrapping muscles.

Most muscles in the legs can be modeled The deltoid muscle wraps over the head
reasonably with via point muscles. of the humerus.

Via Point Muscles

Via point muscles pass through a set of at least two points on their way from origin to insertion. Each of the via points must be attached to a segment or the global reference
frame of the model. The first and the last of the point sequence are special because the muscle is rigidly fixed to them and hence transfers forces in its local longitudinal
direction to them. Conversely, the muscle passes through the interior via points like a thread through the eye of a needle. This means that the muscle transfers only forces to
interior via points along a line that bisects the angle formed by the muscle on the two sides of the via point.

Let us modify the model we have been working on to investigate the properties of via point muscles. Initially we reduce the bulging to facilitate study of the muscle path.

AnyDrawMuscle drw = {
//RGB = {0.554688, 0.101563, 0.117188};
//Opacity = 0.2;
//DrawOnOff = 1;
Bulging = 2;
ColorScale = 1;
//RGBColorScale = {0.957031, 0.785156, 0.785156};
MaxStress = 250000;
};

We then move the insertion point of the muscle a bit further out and closer to the axis of the Arm segment to make room for a via point:

AnySeg Arm = {
r0 = {0.500000, 0.000000, 0.000000};
Mass = 1.000000;
Jii = {0.100000, 1.000000, 1.000000}*0.1;
AnyRefNode Jnt = {
sRel = {-0.5, 0.0, 0};
};
AnyRefNode M1Insertion = {
sRel = {0.3, 0.05, 0};
};
AnyDrawSeg drw = {};
};

The next step is to introduce a new point on the Arm segment to function as the via point:

AnySeg Arm = {
r = {0.500000, 0.000000, 0.000000};
Mass = 1.000000;
Jii = {0.100000, 1.000000, 1.000000}*0.1;
AnyRefNode Jnt = {
sRel = {-0.5, 0.0, 0};
};
AnyRefNode M1Insertion = {
sRel = {0.1, 0.0, 0};
};
AnyRefNode ViaPoint = {
sRel = {0.0, 0.1, 0};
};
AnyDrawSeg drw = {};
};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 114 of 229

We can then introduce the new point in the sequence of points defining the muscle:

AnyViaPointMuscle Muscle1 = {
AnyMuscleModel &Model = .SimpleModel;
AnyRefFrame &Orig = .GlobalRef.M1Origin;
AnyRefFrame &Via = .Arm.ViaPoint;
AnyRefFrame &Ins = .Arm.M1Insertion;
AnyDrawMuscle drw = {
//RGB = {0.554688, 0.101563, 0.117188};
//Opacity = 0.2;
//DrawOnOff = 1;
Bulging = 2;
ColorScale = 1;
//RGBColorScale = {0.957031, 0.785156, 0.785156};
MaxStress = 250000;
};
};

The figure below shows the result:

A muscle can pass through an unlimited number of via points, and the points can be attached to different segments. This can be used to create rather complex kinematic
behaviors of muscles, but it also requires care in the definition to avoid unrealistic muscle paths when the via points move about with the different segments.

From-the-point of view of kinematic robustness, the wrapping muscles are easier to handle than via point muscles, but the price is a much higher computational expense.
Wrapping muscles are the subject of Lesson 4 .

Lesson 4: Wrapping muscles


Many muscles in the body are wrapped over bones and slide on the bony surfaces when the body moves. This means that the contact forces between the bone and the
muscle are always perpendicular to the bone surface, and the muscle may in fact release the contact with the bone and resume the contact later depending on the movement
of the body. Via point muscles are not capable of modeling this type of situation, so the AnyBody Modeling System has a special muscle object for this purpose.

A wrapping muscle is presumed to have an origin and an insertion just like the via point muscle. However, instead of interior via points is passes a set of surfaces. If the
surfaces are blocking the way then the muscles finds the shortest geodetic path around the surface. Hence the name of the class: AnyShortestPathMuscle. The fact that the
muscle always uses the shortest path means that it slides effortlessly on the surfaces, and hence there is no friction between the muscle and the surface.

Enough talk! Let us prepare for addition of a wrapping muscle to our model. If for some reason you do not have a working model from the previous lessons, you can
download one here .

A wrapping muscle needs one or several surfaces to wrap on, so the frst thing to do is to define a surface. For convenience we shall attach the surface to the global
reference frame, but such wrapping surfaces can be attached to any reference frame in the system, including segments. To be able to play around with the position of the
surface, we initially define a point on GlobalRef for the purpose:

// Global Reference Frame


AnyFixedRefFrame GlobalRef = {
AnyDrawRefFrame drw = {
RGB = {1,0,0};
};
AnyRefNode M1Origin = {
sRel = {0.0, 0.1, 0};
};

AnyRefNode CylCenter = {
sRel = {0, 0, -0.2};
};

}; // Global reference frame

Having defined the point, we can proceed to create a surface. The wrapping algorithm in AnyBody will in principle work with any sort of surface including real bone
surfaces, but for the time being only parametric surfaces are used. The reason is that the bony surfaces are really a lot of small planar triangles, and the corners and edges of
the triangles will cause the muscles to slide discontinuously over the surface, which disturbs the analysis result. The parametric surfaces currently available are cylinders
and ellipsoids. Let us try our luck with a cylinder. Go to the class tree, locate the class AnySurfCylinder, and insert an instance into the newly defined node on GlobalRef.
Then define the name of the cylinder, add an AnyDrawParamSurf statement, and change the cylinder parameters as shown below:

AnyRefNode CylCenter = {
sRel = {0, 0, -0.2};

AnySurfCylinder WrapSurf = {
Radius = 0.15;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 115 of 229

Length = 0.4;
AnyDrawParamSurf drv = {};
//CapRatio = 0.100000;
};
};

}; // Global reference frame

Most of this should be self explanatory. However, please notice that the insertion point of the cylinder is at {0, 0, 0.2} corresponding exactly to half of the length of the
cylinder of 0.4. This causes the cylinder to be inserted symmetrically about the xy plane as illustrated below:

The cylinder direction is always z in the coordinate direction of the object that the cylinder is inserted into. So, if the cylinder does not have the orientation you want, then
the key to rotate it correctly is to control the direction of the AnyRefNode that it is inserted into. In fact, let us rotate it just a little bit to make things a bit more interesting:

AnyRefNode CylCenter = {
sRel = {0, 0, -0.2};
ARel = RotMat(20*pi/180,y);

AnySurfCylinder WrapSurf = {
Radius = 0.15;
Length = 0.4;
AnyDrawParamSurf drv = {};
//CapRatio = 0.100000;
};
};

Which causes the cylinder to rotate 20 degrees about the y axis.

There are a couple of things to notice about the cylinder: First of all the graphics looks like the cylinder is faceted. This is not really the case. Graphically it is displayed
with facets out of consideration of the efficiency of the graphics display, but from the point-of-view of the muscle it is a perfect cylinder. The second thing to notice is that
the ends are capped in such a way that the edges are rounded. You can control the curvature of this cap by means of the CapRatio variable that is currently commented out
in the cylinder object definition. If you play a bit around with different values of the cap ratio then you will quickly get a feel for the effect of the variable. The caps allow
you to let the muscle wrap over the edge of the cylinder if necessary.

The next step is to define a wrapping muscle. We shall create one point on the global reference frame and one point on the arm, and we can then articulate the joint and
study the behavior of the wrapping algorithm. The point on the global reference frame is added like this:

// Global Reference Frame


AnyFixedRefFrame GlobalRef = {
AnyDrawRefFrame drw = {
RGB = {1,0,0};
};
AnyRefNode M1Origin = {
sRel = {0.0, 0.1, 0};
};

AnyRefNode M2Origin = {
sRel = {0.0, 0.15, -0.05};
};

Similarly we add a point to the arm:

// Define one simple segment


AnySeg Arm = {
r = {0.500000, 0.000000, 0.000000};
Mass = 1.000000;
Jii = {0.100000, 1.000000, 1.000000}*0.1;
AnyRefNode Jnt = {
sRel = {-0.5, 0.0, 0};
};
AnyRefNode M1Insertion = {

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 116 of 229

sRel = {0.3, 0.05, 0};


};
AnyRefNode M2Insertion = {
sRel = {-0.2, 0.05, 0.05};
};

Notice that we have given the origin and insertion points a bit of offset in the z direction to make the problem a bit more exciting. The offset will cause the muscles to cross
the cylinder in a non-perpendicular path to the cylinder axis such as for instance the pronator muscles of the human forearm do.

It is now possible to define the muscle wrapping over the cylinder. The easiest way to do it is to make a copy of the via point muscle, Muscle1, and then make the
necessary changes:

AnyViaPointMuscle Muscle1 = {
AnyMuscleModel &Model = .SimpleModel;
AnyRefFrame &Orig = .GlobalRef.M1Origin;
AnyRefFrame &Via = .Arm.ViaPoint;
AnyRefFrame &Ins = .Arm.M1Insertion;
AnyDrawMuscle drw = {
//RGB = {0.554688, 0.101563, 0.117188};
//Opacity = 0.2;
//DrawOnOff = 1;
Bulging = 2;
ColorScale = 1;
//RGBColorScale = {0.957031, 0.785156, 0.785156};
MaxStress = 250000;
};
};

AnyShortestPathMuscle Muscle2 = {
AnyMuscleModel &Model = .SimpleModel;
AnyRefFrame &Orig = .GlobalRef.M2Origin;
AnySurface &srf = .GlobalRef.CylCenter.WrapSurf;
AnyRefFrame &Ins = .Arm.M2Insertion;
SPLine.StringMesh = 20;
AnyDrawMuscle drw = {
Bulging = 2;
ColorScale = 1;
MaxStress = 250000;
};
};

The two muscles are very similar in their definitions. They both have an origin and an insertion, and they are both displayed on the screen by means of the same type of
drawing object. Notice that if you have many muscles in a model and you want to have an easy way of controlling the display of all of them, then you can define the
drawing object in an include file, and include that same file in the definition of all the muscles. This way, when you change the display definition in the include file, it
influences all the muscles simultaneously.

The difference between the two definitions is that the via point of Muscle1 has been replaced by a wrapping surface in Muscle2. Shortest path muscles can have any
number of wrapping surfaces specified in sequence just like via point muscles can have any number of via points. In fact, a shortest path muscle can also have via points as
we shall see later.

There is one additional specification necessary for a shortest path muscle. The line:

SPLine.StringMesh = 20;

This line generates a sequence of 20 equidistant points on the shortest path muscle, and these are the points that are actually in contact with the wrapping surface(s). More
points will give you a more accurate solution, but they also require more computation time. For shortest path muscles the computation time can be an important issue.
Solving the shortest path problem is a matter of contact mechanics, and with many muscles in the model this is easily the more computationally demanding operation of all
the stuff that the system does during an analysis. If you have too few points and a complex case of wrapping, the system may sometimes fail to solve the wrapping problem
and exit with an error. In that case the solution is to increase the number of points.

It is time to see what we have done. If you load the model and run the InverseDynamicAnalysis (and have done everything right), you will see the model moving through a
sequence of positions like this:

As mentioned above, wrapping muscles can also have via points. In fact, we can easily change the via point muscle, Muscle1, to wrap over the cylinder even though it also
has a via point:

AnyShortestPathMuscle Muscle1 = {
AnyMuscleModel &Model = .SimpleModel;
AnyRefFrame &Orig = .GlobalRef.M1Origin;
AnyRefFrame &Via = .Arm.ViaPoint;
AnySurface &srf = .GlobalRef.CylCenter.WrapSurf;
AnyRefFrame &Ins = .Arm.M1Insertion;
SPLine.StringMesh = 20;
AnyDrawMuscle drw = {
Bulging = 2;
ColorScale = 1;
MaxStress = 250000;
};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 117 of 229

};

The definition of the two muscle types is very similar, so we only had to change the type from AnyViaPointMuscle to AnyShortestPathMuscle and insert the wrapping
surface and the StringMesh specification. This gives us the following result:

As you can see, both muscles are now wrapping over the cylinder, and we can run the InverseDynamicAnalysis. It seems to work, but the system provides the following
warning:

WARNING - Via-point 'Main.MyModel.GlobalRef.M1Origin' on 'Main.MyModel.Muscle1.SPLine' is located below the wrapping surface


'Main.MyModel.GlobalRef.CylCenter.WrapSurf'.

This is a warning that you will see rather frequently when working with complex models with wrapping. The warning comes when one of the end points or a via point is
located below the surface over which the muscle is supposed to wrap. This means that it is impossible for the muscle to pass through the via point without penetrating the
wrapping surface. In this case the system chooses to let the muscle pass through the via point and the back to the wrapping surface as soon as possible. In the present case,
the origin point of Muscle1 is only slightly below the cylinder surface, so the problem can be rectified by a small offset on the origin point:

AnyRefNode M1Origin = {
sRel = {0.0, 0.15, 0};
};

If you are analytically inclined, you may be thinking that the muscles might equally well pass on the other side of the cylinder. And you are quite right. The reason why
both muscle pass over the cylinder rather than under is that this is the side that is the closest to the muscles' paths before the wrapping is resolved. This means that we can
make a muscle wrap on another side of a wrapping surface by making sure that its initial position is closer to the side we want it to wrap on. The way to do this is to
specify one or more so-called initial wrapping vectors. These are really points that the muscle initially should pass through. You can specify as many of these points as you
like. In the example below we have used two:

AnyShortestPathMuscle Muscle2 = {
AnyMuscleModel &Model = .SimpleModel;
AnyRefFrame &Orig = .GlobalRef.M2Origin;
AnySurface &srf = .GlobalRef.CylCenter.WrapSurf;
AnyRefFrame &Ins = .Arm.M2Insertion;
SPLine.StringMesh = 20;
SPLine.InitWrapPosVectors = {{-0.2, -0.2, 0}, {-0.05, -0.2, 0}};
AnyDrawMuscle drw = {
Bulging = 2;
ColorScale = 1;
MaxStress = 250000;
};
};

Notice that the InitWrapPosVectors like the StringMesh is part of an object called SPLine. This is an object in its own right that gets defined automatically inside a shortest
path muscle. It is a special kind of kinematic measure that is really a string that wraps just like a muscle but does nothing else than measure its own length. These objects
can be used outside the muscle definition for various purposes in the model, for instance for definition of springs or rubber bands.

After you load the model with the added InitWrapVectors, try using the Step button rather than the run button. This will show you how the system uses the
InitWrapVectors to pull the muscle to the other side of the cylinder:

If you keep pressing the step button you will see how the muscle now wraps on the other side of the cylinder.

With the kinematics of muscles well under control, we can proceed to another important and interesting topic, Lesson 5: Muscle models .

Lesson 5: Muscle models


Muscle model is a description of how a muscle behaves under different operating conditions. There are two schools of thought within this area.

 The first school pursues phenomenological models based on the classical work by A.V. Hill . These models are usually based on a description of a muscle as a
contractile element in combination with a number of elastic elements. While these models make no attempt to directly model the microscopic mechanisms of muscle

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 118 of 229

contraction, they do reproduce many properties of muscle behavior quite well, and most models of this class can be implemented with great numerical efficiency.
 The second school attempts to directly model the microscopic physical phenomena of cross bridge activity in muscle contraction. The origin of these models is
usually attributed to A.F. Huxley , and they lead to differential equations and consequently to much more computationally demanding models.

The AnyBody Modeling System requires muscle models because it must take the strength of different muscles into account when distributing the load over them. A
traditional muscle model is one that takes an activation signal and a present muscle state as input and produces a force as output. But inverse dynamics, as it is used in the
AnyBody Modeling System, does not work quite like that. Instead of taking an activation signal as input, AnyBody produces the muscle active state as output. This means
that typical muscle models from the literature must be mathematically reversed before they can be used in the AnyBody Modeling System. Depending on the complexity of
the muscle model, this may be more or less difficult.

AnyBody has three muscle models available differing in complexity and accuracy of their representation of physiological muscles. All of these are phenomenological, i.e.
they make no attempt to capture the complexity of cross bridge dynamics. You may ask why we would want three different models? Why don't we just use the better of the
three models? The answer is that accurate models are good, but they are never more accurate than the input data, and it is often difficult to find the detailed physiological
data that the complex models require. Instead of basing a computation on data of unknown accuracy it is often preferable to go with a simpler model where the
approximations are clear.

In short, AnyBody has the following muscle models available

AnyMuscleModel This is the simplest conceivable muscle model, and it is the one we have used in the preceding lessons of this tutorial. The only input to the
model is the muscle's presumed isometric strength, F0, i.e. the force that the muscle can exert in a static condition at its optimum length. F0 is
often believed to be proportional to the physiological cross sectional area of the muscle, and it is possible to find that dimension for most
significant muscles in the human body from cadaver studies reported in the scientific literature.

It is important to stress that the strength of this muscle model is independent of the muscle's current length and contraction velocity. It is known
for a fact that muscles do not behave that way, but for models with moderate contraction velocities and small joint angle variations even this
simple model will work reasonably well. Such has been shown to be case for bicycling and gait.
AnyMuscleModel2ELin This model presumes that the muscle strength is proportional to the current length and to the contraction velocity. This means that the muscle
gets weaker when its length decreases or the contraction velocity increases. In other words, the muscle strength is bilinear in the length and
velocity space. The model also presumes that the tendon is linearly elastic and as such contains two elements: A contractile element (the
muscle), and a serial-elastic element (the tendon).

The rationale behind this model is that a muscle has a certain passive elasticity built into it. If the muscle it stretched far enough, the passive
elasticity will build up force and reduce the necessity for active muscle force. This is in some cases equivalent to an increase of the muscle's
strength. Notice, however, that this model has the significant drawback that the force can be switched off even if the muscle is stretched very
far, while the true passive elasticity will always provide a force when it is stretched.
AnyMuscleModel3E This is a full-blown Hill model that takes parallel passive elasticity of the muscle, serial elasticity of the tendon, pennation angle of the fibers,
and many other properties into account. However, it also requires several physiological parameters that may be difficult to get or estimate for a
particular muscle in a particular individual.

In the reminder of this lesson we shall experiment with the consequences of the different muscle models. The AnyScript model from the previous lesson will suffice very
nicely. You can download a functional version of the model here:

MuscleDemo.5.any

AnyMuscleModel2ELin

Right-click and save the file to your local disk, and subsequently open the model in the AnyBody Modeling System. We have already seen the consequences of using the
simple muscle model, so we shall proceed directly to the two-element muscle, the AnyMuscleModel2ELin. Let us define such a muscle model. If you click the Classes tab
in the tree view left of the edit window, expand the class tree, right-click the AnyMuscleModel2ELin class, and insert a template, you will obtain the following:

AnyMuscleModel SimpleModel = {
F0 = 100;
};

AnyMuscleModel2ELin <ObjectName> = {
F0 = 0;
Lfbar = 0;
Lt0 = 0;
Epsilonbar = 0;
V0 = 0;
};

Let us briefly review the parameters:

Parameter Function
F0 In the simple muscle model, F0 is simply the strength of the muscle. In this two-parameter model, F0 is the ideal strength, i.e. the strength of the muscle at
neutral fiber length and zero contraction velocity. F0 is measured in force units, i.e. Newton.
Lfbar The neutral fiber length, i.e. the length of the contractile element at which the muscle has the strength of F0. Lfbar is measured in length units, i.e. meters.
Lt0 The muscle's total length from origin to insertion can be divided into two parts: the length of the muscle's contractile element plus the length of the tendon.
The tendon is considered in this model to be linearly elastic, and Lt0 is the slack length of the tendon, i.e. the length when it is taut but carrying no force.
Lt0 is measured in length units, i.e. meters.
Epsilonbar This parameter controls the elasticity of the tendon. The physical interpretation is that it is the tendon's strain when subjected to a force of F0. Prescribing a
strain rather than an ordinary spring stiffness is based on the idea that the tendon thickness must be related to the strength of the muscle: strong muscles need
strong tendons. Hence, Epsilonbar can be presumed with good accuracy to be the same for a wide variety of very different muscles. Epsilonbar is measures
in fractions and is therefore dimensionless.
V0 This model presumes that the muscle's strength depends linearly on its contraction velocity. V0 is measured in absolute velocity, i.e. m/s.

We can study the significance of the parameters in more detail, if we formulate the strength mathematically:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 119 of 229

You can probably recognize the variable names in the table above from the symbols in the equation. As you can see, this is really a bilinear model, where the variables are
Lm and Lmdot. The strength of the muscle vanishes is any of the two parentheses becomes zero. This can happen if either Lm, i.e. the current length of the contractile
element, becomes half the length of Lfbar, or if Lmdot becomes equal to V0. Please notice that Lmdot is negative when a muscle is contracting, so meaningful values of
V0 must also be negative. The system automatically truncates negative values of the strength expression to zero.

In a few moments, when we start playing around with the muscle model in AnyBody, you wll recognize these properties in the available muscle variables in the Chart
View.

Let us assign a name and some reasonable parameters to our two-element muscle model:

AnyMuscleModel2ELin Model2 = {
F0 = 200;
Lfbar = 0.3;
Lt0 = 0.5;
Epsilonbar = 0.05;
V0 = -8.0;
};

The parameters here are more or less random. In a moment we shall explain the ones that are less random, but first we must assign the new model to Muscle1:

AnyShortestPathMuscle Muscle1 = {
AnyMuscleModel &Model = .Model2;
AnyRefFrame &Orig = .GlobalRef.M1Origin;
AnyRefFrame &Via = .Arm.ViaPoint;
AnySurface &srf = .GlobalRef.CylCenter.WrapSurf;
AnyRefFrame &Ins = .Arm.M1Insertion;
SPLine.StringMesh = 20;
AnyDrawMuscle drw = {
Bulging = 0;
ColorScale = 1;
MaxStress = 250000;
};
};

We are ready to run the analysis again and investigate the results. Pick the InverseDynamicAnalysis in the tree of operations and click the Run button. Then open a new
Chart View and expand the tree in the Chart View as far down as Muscle1. You will see a whole list of muscle properties that you can chart simply by clicking them. Let
us initially see how the properties Lm and Lmdot affecting the strength of the model. You can plot several properties simultaneously in the Chart View by use of an asterix
in the variable specification field at the top of the window like this:

Now we can compare the variation of Lm and Lmdot to our settings of Lfbar and V0. Lm seems to vary between approximately 0.31 and 0.15. With an Lfbar of 0.3 (=
2x0.15) this means that the muscle must come close to the minimum length at which is has any strength when we approach the end of the movement. Lmdot varies between
-0.24 and -0.06, and this is far from its speed limit V0 = -8, so the contraction speed is not expected to have much effect. We can investigate the effect very easily simply
by clicking the Strength property of the muscle and obtain the following graph:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 120 of 229

The strength does indeed decrease drastically from around 200 N to almost nothing as we expected when the muscle contracts.

Now that we have muscle data available, let us briefly review the parameters presented in the Chart View:

 Fin is a force, but it has not physiological significance for a muscle except for internal purposes. The reason why it is included in the output is that it is inherited
from the AnyScript classes that a muscle is derived from.
 Fout is a force, but it has not physiological significance for a muscle except for internal purposes. The reason why it is included in the output is that it is inherited
from the AnyScript classes that a muscle is derived from.
 Lmt is the total length of the muscle-tendon unit, i.e. the origin-insertion length.
 Lm is the length of the muscle's contractile element.
 Lt is the length of the tendon. This is not necessarily the same as Lt0 because the tendon is linearly elastic and therefore stretches slightly with the force.
 LmtDot is the rate of change of Lmt, i.e. the length change velocity of the total muscle-tendon unit.
 LmDot is the contraction velocity of the contractile element.
 Activity is the muscle active state in fractions of maxmum voluntary contraction.
 CorrectedActivity for this muscle model is the same as Activity.
 Fm is the force in the muscle's contractile element. For this muscle type it is equal to the total force in the muscle-tendon unit because the muscle does not have any
parallel components.
 Ft is the force in the tendon. For this muscle model it is the same as Fm.
 Fp is not relevant for this type of muscle model.
 Strength is the muscle's strength at each moment of the movement.
 Ft0 is not relevant for this type of muscle model.
 Ft0Grad is the derivative of tendon force with respect to active state. For this muscle model is amounts to exactly the same as the Strength variable, but for muscles
with parallel elasticity the two properties will be different.
 PennationAngle is not relevant for this muscle model type.
 EPOTt is the potential elastic energy in the tendon.
 EPOTp is the potential elastic energy in the parallel-elastic element, which is not included in this muscle model.
 EPOTmt is the total elastic potential energy in the muscle-tendon unit.
 Pt is not relevant for this muscle model.
 Pm is the mechanical power exerted by the muscle's contractile element.
 Pmt is the mechanical power of the muscle-tendon unit on the skeleton.
 Pmet is a crude estimate of the metabolic power consumption of the muscle taking different efficiencies for concentric and eccentric work into account.

We have seen how the length of the muscle affects its strength, but what about the velocity? Well, the specified values of -8 m/s is a reasonable estimate for many
physiological muscles, but let us try to decrease it and thereby make the muscle more sensitive to contraction velocity:

AnyMuscleModel2ELin Model2 = {
F0 = 200;
Lfbar = 0.3;
Lt0 = 0.5;
Epsilonbar = 0.05;
V0 = -0.3;
};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 121 of 229

A value of V0 = -0.3 is close to the contraction velocity of the muscle in the beginning of the simulation. This, this decreases the strength of the muscle significantly as we
can see by reloading, rerunning and plotting the Strength variable again:

Instead of being monotonically decreasing, the muscle strength now improves slightly in the initial part of the simulation, but it is all through the simulation significantly
weaker than before. The initial increase is due to the beneficial effect of the decreasing contraction velocity, so this muscle model in spite of its simplicity is capable of
balancing several of the effects of real muscle physiology.

Another of the important input parameters in this example is the nominal tendon length, Lt0. This is a parameter that has a very large influence on the muscle's
performance. The total origin-insertion length of the muscle-tendon unit depends on the size and posture of the body. The muscle spans this length with the sum of muscle
length, Lm, and tendon length, Lt, such that Lmt = Lm + Lt. Both Lm and Lt change during the movement of the body. Lt is given by its initial length, Lt0, and the elastic
deformation. Lm has to take up whatever rest of Lmt that is available after Lt has been subtracted. In some cases, the tendon is significantly longer than the muscle, and
this means that a relatively small variation of the tendon length results in a large relative variation of the portion of Lmt that the muscle has to fill. Obviously Lt0 plays a
significant role for Lt and hence influences the working length of the muscle. Let us investigate this effect by reducing Lt0:

AnyMuscleModel2ELin Model2 = {
F0 = 200;
Lfbar = 0.3;
Lt0 = 0.3;
Epsilonbar = 0.05;
V0 = -0.3;
};

This reduction of the tendon length from 0.5 to 0.3 meters is very significant compared to the nominal muscle fiber length of Lfbar = 0.3 m. Reducing the length of the
tendon increases the length and thereby the strength of the muscle:

The interdependency between the stretch of the tendon, the length of the muscle, and the strength of the muscle is the origin of another approximation in the model: The
system computes the changed length of the muscle due to the stretching of the tendon, but this length change is not taken into account in the computation of the muscle
strength. Nevertheless, let us investigate how the stretch of the tendon influences the muscle. We shall define an external load on the arm, which causes the tendon to
stretch. But before we change anything, let us just notice that the variation of muscle length, Lm, over the movement in the absence of an external load is as shown below:

Definition of an external force requires two new elements in the model: The force itself and a new node on the arm, which we shall call hand, to which the load can be
applied:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 122 of 229

// Define one simple segment


AnySeg Arm = {
r = {0.500000, 0.000000, 0.000000};
Mass = 1.000000;
Jii = {0.100000, 1.000000, 1.000000}*0.1;
AnyRefNode Jnt = {
sRel = {-0.5, 0.0, 0};
};
AnyRefNode M1Insertion = {
sRel = {0.3, 0.05, 0};
};
AnyRefNode M2Insertion = {
sRel = {-0.2, 0.05, 0.05};
};
AnyRefNode ViaPoint = {
sRel = {0.0, 0.1, 0};
};
AnyRefNode Hand = {
sRel = {0.5, 0.0, 0};
};
AnyDrawSeg drw = {};
};

AnyForce3D Load = {
AnyRefNode &Attachment = .Arm.Hand;
F = {-100, -100, 0};
};

The load is pointing down and backward at a 45 degree angle, so that it changes its moment arm from positive to negative a shortly after the midpoint of the analysis. This
causes the muscle length to vary in the following fashion:

The interesting point here is that with the long tendon and the high load, the muscle no longer contracts uniformly. In fact, the muscle extends for much of the movement
due to the decreasing load which causes the elastic tendon to contract instead.

While the two-parameter muscle model captures many of the properties of real muscles it also fails to reflect important parts of muscle physiology, so it should be applied
with care. In particular it does not model passive elasticity. The following section presents a full-blown Hill-type model, which does not have these shortcomings.

AnyMuscleModel3E

So far we have been focusing our attention on Muscle1 in the demo model and left Muscle2 with the simple muscle model. Let us briefly study what Muscle2 is actually
doing (if you need an updated working model, you can download it here: MuscleDemo.5-2.any ). Muscle2 wraps about the cylinder and obviously extends significantly as
the arm turns upward. If you run the analysis and plot the length of Muscle2, you will see that it increases 0.7 to 1 meter. For a normal muscle (actually a muscle of this
size would probably be found in a giraffe) a stretching of that magnitude would almost certainly lead to some passive force in the muscle.

Passive force is what comes from the structural integrity of the muscle. If we disregard the active properties of the muscle and think of it as simply a piece of material that
we can stretch, then the material will provide a passive resistance depending on how far we stretch it. This is the passive component of the muscle force. We can easily find
passive muscle force in our own bodies: When we bend forward and try to touch our toes with the straight legs, then most of us will feel the hamstrings getting very taut.
This is passive elasticity. The two-element muscle model of the preceding section handles the presence of this elasticity by increasing the strength of the muscle, and this
works fine if the muscle is supposed to be active in the sense that the model in such a state would predict a high force with a low muscle activity. But the passive muscle
force cannot be switched off, so it will still be present even if it is disadvantageous, and the two-element model will not predict this.

The AnyMuscleModel3E is a full-blown Hill-type muscle model that does not suffer from this deficiency. It is called a three-element model because it has the following
components:

1. A contractile element (CE) representing the active properties of the muscle fibers.
2. A serial-elastic (T) element representing the elasticity of the tendon.
3. A parallel-elastic element (PE) representing the passive stiffness of the muscle fibers.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 123 of 229

The figure above is a schematic representation of the muscle model. We can get a complete impression of the parameters of the model if we pick the model from the Class
List as we have done before and insert a template into our AnyScript model:

AnyMuscleModel2ELin Model2 = {
F0 = 200;
Lfbar = 0.3;
Lt0 = 0.3;
Epsilonbar = 0.05;
V0 = -0.3;
};

AnyMuscleModel3E <ObjectName> = {
F0 = 0;
Lfbar = 0;
Gammabar = 0;
Epsilonbar = 0;
Lt0 = 0;
Fcfast = 0;
//Jt = 3;
//Jpe = 3;
//K1 = 2;
//K2 = 8;
//PEFactor = 5;
};

Several of these elements are described already in the two-element model above, but some are new and described in the table below. No excuse we can make is going to
soften the fact that muscle modeling at this level of detail is a technical matter, and it is not possible to describe the physiological and mathematical background in detail.
Instead please refer to the publications at the end of this lesson for further information:

Gammabar Gamma is the so-called pennation angle. It reflects that fact that most muscles have the fibers misaligned with the directions of action of the muscle. Gamma
changes when the muscle extends or contracts, and Gammabar is the value of Gamma in the muscle's neutral position. It is possible to find values for
Gammabar for most major muscles in the human body in the anatomical literature. Gammabar is measured in radians.
Fcfast Muscle fibers come in two flavors: fast twitch and slow twitch, and the composition of these vary between the muscles as well as between individuals. Fast
fibers, as the name indicates, have the ability of fast action at the cost of stamina, and slow fibers have opposite properties. Sprint runners have a high
proportion of fast twitch muscles while marathon runners have many slow twitch muscles.

Fcfast is the fraction of fast twitch fibers in the muscle. It is a fraction between 0 and 1 and hence dimensionless.
Jt and Jpe Jt and Jpe are elasticity factors for the tendon (serial-elastic) and parallel-elastic elements respectively. The background of these parameters is that the model
presumes a nonlinear elasticity of these elements, and the precise shape of the force-deformation characteristics of the element are determined by Jt and Jpe
respectively. In essence, Jt and Jpe are material constants and should not vary too much between different muscles or individuals.

Recommended values are Jt = Jpe = 3.0. These two parameters are dimensionless.
K1 and K2 These two factors are used only to ensure a reasonable relationship between fiber length, fiber composition, and Fcfast. As discussed in the preceding
section, the strength of a muscle tapers off when its contraction velocity grows. Rather than working with a given maximum contraction speed as the two-
element model does, K1 and K2 enable us to link the maximum contraction speed to the physiological properties of the muscle. The idea is that muscles with
longer fibers and a larger fraction of fast twitch muscles should have a higher maximum contraction velocity.

Preferred values for K1 and K2 differ significantly between authors in the scientific literature, but a good guess would be K1 = 2 and K2 = 8. K1 and K2
formally have the unit of fractions per time unit, i.e. s -1 .
PEFactor This factor is related to Jpe. Where Jpe controls the shape of the nonlinearity, PEFactor controls the steepness of the force in the parallel-elastic element as it
is elongated. If we imagine a completely inactive muscle and load the muscle with a force corresponding to the active strength of the muscle, i.e. F0, then the
length of the elongated muscle fibers will be PEFactor x Lfbar. In other words PEFactor is a dimensionless measure of the flexibility of the parallel-elastic
element of the muscle.

Plausible values for PEFactor would be between 1.5 and 5 where the lower end of the interval requires a very careful tuning of the muscle to the skeleton to
avoid unreasonably large passive forces.

Knowing the significance of the different parameters, let us pick reasonable values for Muscle2 and study their influences:

AnyMuscleModel3E Model3 = {
F0 = 100;
Lfbar = 0.3;
Gammabar = 30*pi/180;
Epsilonbar = 0.05;
Lt0 = 0.5;
Fcfast = 0.4;
Jt = 3.0;
Jpe = 3.0;
K1 = 2;
K2 = 8;
PEFactor = 5;
};

Notice that Lfbar + Lt0 = 0.8, which is in the range of the Lmt variation of Muscle2. This is important because it gives the muscle a reasonable chance of spanning the
origin-insertion length.

We also have to associate Muscle2 with the new muscle model:

AnyShortestPathMuscle Muscle2 = {
AnyMuscleModel &Model = .Model3;
AnyRefFrame &Orig = .GlobalRef.M2Origin;
AnySurface &srf = .GlobalRef.CylCenter.WrapSurf;
AnyRefFrame &Ins = .Arm.M2Insertion;
SPLine.StringMesh = 20;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 124 of 229

SPLine.InitWrapPosVectors = {{-0.2, -0.2, 0},{-0.05,-0.2, 0}};


AnyDrawMuscle drw = {
Bulging = 0;
ColorScale = 1;
MaxStress = 250000;
};
};

Finally, to have a more clean-cut case, we temporarily remove the external force that we previously added

/*
AnyForce3D Load = {
AnyRefNode &Attachment = .Arm.Hand;
F = {-100, -100, 0};
};

*/

We are ready to try running the InverseDynamicAnalysis again. Load the model, pick InverseDynamicAnalysis in the operations tree, and click the Run button. The arm
should move as is did in the previous section. Now, using a Chart View we can investigate the behavior of the new muscle. In the Chart View's tree, expand the folders as
far as Muscle2, and try charting some of the parameters.

The key to understanding the muscle's behavior is to study the forces in the muscle's different elements. The chart of Fm, which is the force in the muscle's contractile
element, is very uninteresting. This muscle does not contribute to carrying the load, and hence the system does not activate it. But the muscle is not without force. The
property Fp, which is the force in the parallel-elastic element of the muscle has the following behavior:

In the initial phase of the movement, the parallel-elastic element is slack and adds no force to the muscle. But as the muscle gets extended, the passive muscle force sets in,
and it continues to rise as the movement progresses. Notice that this passive force acts against the movement and hence requires Muscle1 to work that much more. But the
passive force has another interesting effect, which we can see if we chart the property Lt, i.e. the length of the tendon (Notice that we have changed the scale of the ordinate
axis):

From the time the passive force sets in, the tendon starts to elongate a little bit.

The total origin-insertion length of the muscle-tendon unit is the tendon length plus the muscle length, i.e. Lm + Lt. When Lt is stretched, the effect is that the muscle fibers
stretch that much less, and since the muscle's strength depends on the momentary length of the contractile element, the strain in the tendon can influence the strength of the
muscle. The figure above shows that the tendon stretch is rather limited and we might therefore expect that the influence on the muscle strength is also limited. However,
some muscles in the human body (for instance m. soleus) have the property of relatively short fibers and a long tendon, and in this case the effect can be significant.

The three-element muscle model attempts to take this into account in the computation of muscle activity, coping with the fact that this is a catch 22 type of problem in
inverse dynamics:

 We cannot compute the elongation of the tendon until we know the force in the muscle.
 We do not know the force in the muscle until we have solved the muscle recruitment problem.
 To solve the muscle recruitment we need the momentary strength of each muscle.
 The momentary strength depends on the elongation of the tendon.

We seem to be faced with a circular dependency between the muscle properties. The three-element model copes with this through a one-time correction: It recruits the
muscle without taking the tendon elongation into account. Then it computes the tendon elongation. Finally, it computes the influence of the elongation on the muscle's
strength and corrects the muscle activity to the level that provides the necessary force with the modified strength. This is only an approximative solution because the
change of muscle strength may theoretically alter the distribution of force between the muscles, and this alteration is not done by the system; the correction is local to each
muscle.

So much for passive properties. It is more instructive to investigate a muscle model with active force. The easiest way to do so is to enable our hand force again and change
it to point directly upward. This causes the previously inactive Muscle2 to become active:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 125 of 229

// Define one simple segment


AnySeg Arm = {
r = {0.500000, 0.000000, 0.000000};
Mass = 1.000000;
Jii = {0.100000, 1.000000, 1.000000}*0.1;
AnyRefNode Jnt = {
sRel = {-0.5, 0.0, 0};
};
AnyRefNode M1Insertion = {
sRel = {0.3, 0.05, 0};
};
AnyRefNode M2Insertion = {
sRel = {-0.2, 0.05, 0.05};
};
AnyRefNode ViaPoint = {
sRel = {0.0, 0.1, 0};
};
AnyRefNode Hand = {
sRel = {0.5, 0.0, 0};
};
AnyDrawSeg drw = {};
};

AnyForce3D Load = {
AnyRefNode &Attachment = .Arm.Hand;
F = {0, 10, 0};
};

With this we can run the InverseDynamicAnalysis again and get the muscle to do some work. Let us systematically investigate the output:

This is a force, but it has not physiological significance for a muscle except for internal purposes. The reason why it is included in
Fin
the output is that it is inherited from the AnyScript classes that a muscle is derived from.
This is a force, but it has not physiological significance for a muscle except for internal purposes. The reason why it is included in
Fout
the output is that it is inherited from the AnyScript classes that a muscle is derived from.

The length of the muscle-tendon unit. If you plot this property you will see that it rises almost linearly as the muscle is extended.
Lmt Closer investigation, however, will reveal that it is offset slightly by the nonlinearity caused by the elongation of the tendon due to
the varying force.

Lm The length of the contractile element.

The length of the tendon. This appears to be constant, but the tendon length actually changes slightly over the movement with the
Lt
changes of muscle force as described above.

LmtDot The contraction velocity of the muscle-tendon unit. The value is positive because the muscle is getting longer.

LmDot The contraction velocity of the contractile element of the muscle. The value is positive because the muscle is getting longer.

This is the muscle activity before correction for the change in muscle length caused by the elastic elongation of the muscle. The
Activity complicated variation is caused by the interplay between change of moment arm of the applied force, the passive force in the
muscle and the change of muscle strength with the contraction.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 126 of 229

This is the muscle activity after correction for the tendon elongation. The difference between this graph and the one above is that
the activity toward the end is higher after correction. This can be difficult to understand and illustrates the complexity of muscle
Corrected- modeling. The reason is the following: The force in the muscle reduces towards the end of the movement. When the force is
Activity reduced, the tendon contracts, and this means that the muscle must elongate even more. Since the muscle length is already in the
interval where further elongation will cause decreased strength, the tendon contraction has the effect of increasing the muscle
activity.

The force in the contractile element is decreasing throughout the movement because the moment arm of the external force is
Fm
reducing and also because the passive force in the muscle is contributing more and more to balancing the load.

The tendon force shows the reduction of the mucle action by virtue of the reduced external force's moment arm alone. A simplified
Ft
explanation is that Ft = Fm + Fp, but this is not entirely true because we also have to account for the pennation angle.

Fp The passive force in the muscle increases as the muscle is stretched.

Strength This is the strength of the muscle. It is not corrected for the tendon elongation.

The hypothetical force that the tendon would have if the activity of the muscle were zero. The reason why this is slightly different
Ft0 from Fp is that Ft0 acts directly along the action line of the muscle while Fp is diverted by the pennation angle. This property is
mostly interesting to scientists involved in detailed modeling of single muscles.

The gradient of Ft0 with respect to the muscle activity. For mathematical reasons this is equal to the Strength, and the two graphs
Ft0Grad are identical. The reason why this property is included under to different names is that the simple muscle model, from which this
model is derived, does not have Ft0Grad and hence needs a Strength property.

Pennation- The pennation angle is the angle between the muscle fiber direction and the muscle line of action. This angle changes when the
Angle muscle contracts and elongates, and the model takes this effect into account.

EPOTt The elastic potential energy stored in the tendon.

EPOTp The elastic potential energy stored in the parallel-elastic element of the muscle.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 127 of 229

The elastic potential energy stored in the entire muscle-tendon unit. This can have some practical significance for investigation of
EPOTmt
movement economy and sports activities in general.

Pt The rate of change of elastic potential energy in the tendon.

Pm The mechanical power of the contractile element.

The mechanical power of the entire muscle-tendon unit, i.e. the rate of work performed on the skeleton. Notice that the power is
Pmt negative because the muscle is extending against the force. Muscles behaving like this in the human body are often termed
antagonistic muscles.

A crude estimate of the metabolism in the muscle. The estimate is based on presumed efficiencies of the contractile element of
Pmet
25% for concentric work and -120% for eccentric work. The model does not take the metabolism of isometric force into account.

Calibration

One of the practical challenges in working with detailed muscle models in complex musculoskeletal systems is the dependency on defined tendon length, Lt0. A brief
experiment with our model can reveal where the difficulty lies. In the model we have just investigated, the activity of Muscle2 has the following development over the
movement:

But what would happen if our guess of tendon length, Lt0, in the muscle model definition was just slightly off the correct value? Well if we change the current value from
0.5 m to 0.45 m, i.e. a reduction of 10%, we get the following activity:

Not only is the shape of the graph different; the maximum activity is also significantly higher. An error of 10% in an anthropometric data value is not uncommon
considering the accuracy of measurement methods and variation between individuals, and if the influence on the final result is as strong as this, we would not be able to
trust our results. The problem is even more difficult if we desire to scale models up and down in size: Muscles pass along complex paths from origin to insertion, and the
lengths of these paths do not scale in a simple fashion with, for instance, overall subject height.

As usual in biomechanical modeling, the solution can be found by relying on nature's ability to make the best of its resources. Nature has not equipped humans with
tendons whose lengths are very disadvantageous for our normal activities. We can use this knowledge to calibrate the tendon lengths for an individual of a certain size.
Quite simply, we shall presume that the tendon lengths are calibrated by nature to provide the muscles with optimum fiber lengths at certain postures. The AnyBody
Modeling System provides two ways to do that: One is cheap and dirty, and the other one requires additional information. Let us take a closer look at them:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 128 of 229

Cheap and dirty

The cheap and dirty solution is of course easily available but also not recommended for accurate analysis.

You must make an AnyBodyCalibrationStudy, which is the study type specially designed for doing calibrations of muscle and ligament objects. The
AnyBodyCalibrationStudy needs a model definitions and motion/posture information in order to perform the calibration. In the cheap and dirty solution, we simply use the
same model definition, hereunder the motion/posture, of your original AnyBodyStudy. You simply need to insert the same references to the model in the
AnyBodyCalibrationStudy folder as you have in your AnyBodyStudy model.

Adding a single AnyBodyCalibrationStudy object next to your AnyBodySyudy this way, allow you to run its operation called TendonLenghtAdjustment. If you run it, you
will see the model moving as it does when running the InverseDynamics operation of the original AnyBodyStudy. But when the analysis is done, the following message
appears in the message window:

The tendon length of muscle Main.MyModel.Muscle2 was calibrated. The muscle properties have been updated.

Try running the InverseDynamics again and plot the Activity of Muscle2. You should see the following:

As you can see, this is again very different from what we have seen before. Plotting the strength will reveal what has happened:

What the MuscleCalibrationAnalysis does is to run through the specified movement and compute the variation of the origin-insertion length of the muscle. It subsequently
changes the user-defined value of Lt0 such that the length of the contractile element equals the optimum fiber length, Lm0, when the origin-insertion length is at its mean
value. Notice that this does not necessarily correspond to the length when 50% of the movement has passed.

The rationale behind this method of tendon length calibration is that if you analyze a movement that is representative for what the body is created to do, then the muscles
should probably attain their optimum fiber lengths somewhere safely within the interval of movement. Naturally this is not a very accurate way of doing it, and it will not
work if you are modeling a movement that is outside the typical posture of the joints in the model.

Please notice that the tendon lengths specified in the AnyScript model are not altered by this method. Every time you reload the model you must run the
MuscleCalibrationAnalysis again.

Detailed calibration

There is a more accurate and detailed way of calibrating tendons, but it requires additional information. More precisely it calibrates the tendon lengths at user-defined joint
postures. So each muscle is associated with a certain set of joint postures for which the muscle is presumed to be at its neutral position. Please notice that the set of neutral
joint postures is in principle different for each muscle in the system. In practice the calibration usually takes place on sets of muscles at a time, where all the muscles in a
set is calibrated at the same joint postures. This way, all the muscles in a complicated system can be calibrated with a reasonable number of operations.

Detailed calibration of tendon lengths is covered in the "Inverse Dynamics of Muscle Systems" tutorial . Calibration of ligaments is much the same type of process and is
described in detail in the Ligament tutorial, Lesson 7 .

But before we come to ligaments we must cover one last aspect of muscle modeling, namely General Muscles. They are the topic of the next lesson, Lesson 6 .

References

Hill, A.: The heat of shortening and the dynamics constants of a muscle. Proc. Roy. Soc. B., 126, 136-195, 1938.

Huxley, A.: Muscle structure and theories of contraction, Progr. Biophys. 7, 255-318.

Zajac, F.E.: Muscle and Tendon: Properties, Models, Scling, and Application to Biomechanics and Motor Control. Critical Reviews in Biomedical Engineering, 17, 359-
410, 1989.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 129 of 229

Lesson 6: General muscles


Physiological muscles are truly amazing machines, and despite many attempts it has not been possible to make technical actuators that are as light and efficient as natural
muscles. As you may have seen in the preceding sections, the mathematical modeling of muscles is not an easy task either. But once it has been done, we can use some of
the properties of muscles to our advantage. We would like these "muscles" to be able to have a slightly more general formulation than physiological muscles, which are
confined to acting along strings.

The solution is the AnyGeneralMuscle class. This type of muscle is capable of acting on Kinematic Measures. Kinematic measures is an abstract class representing
anything you can measure on a model, and there is in fact an entire tutorial lesson devoted to the subject in the section on The Mechanical Elements . Some examples are:

 A general muscle working on a distance measure between two points becomes simply a linear force provider, or in fact a reaction provider in the sense that the force
is not predetermined but will become whatever equilibrium requires.
 A general muscle working on an angular measure, for instance a joint angle, becomes a torque provider.
 A general muscle working on a Center of Mass measure becomes an abstract force working on all segments of the body contributing to the center of mass.

This lesson demonstrates how general muscles can be used for a variety of modeling tasks.

Muscles as joint torque providers

One of the purposes of the AnyBody Modeling System is to be able to model the musculoskeletal system to a realistic level of detail. However, there is a place in the world
for traditional inverse dynamics, where the muscles are disregarded and the body is balanced entirely by joint torques. This type of analysis can provide important
information about the function of limbs and joints, and it is extremely numerically efficient.

Joint torque inverse dynamics can be accomplished by adding general muscles to the joints to replace the physiological muscles of the body. This way, the "muscle forces"
computed in the general muscles will simply be the joint torques.

The example from the preceding lessons is not well suited to play with joint torques, so please download a new example to start on by clicking here (right-click and save to
disk). This is in fact a simplified version of the simple arm example from the Getting Started with AnyScript tutorial, where the muscles have been removed. The model
has two segments, an upper arm and a forearm, and is attached to the global reference frame at the shoulder. It has a 100 N vertical load acting downwards at the hand.

The lack of muscles means that the model cannot currently do an inverse dynamics analysis. If you try to run the InverseDynamicAnalysis operation, you will get the
following error message:

ERROR : C:\Documents and Settings\jr\My Documents\AnyScripts\demo\MuscleDemo\MuscleDemo.6.any(103) : ArmStudy : Muscle recruitment analysis failed,
simplex solver found that problem was unbounded.

which is a mathematical way of stating that the model cannot be balanced in the absence of muscles. In this case we are not going to add real muscles. Instead we shall add
general muscles to the revolute joints. The best way to introduce a general muscle is to insert it from the class tree. Place the cursor after the Drivers folder, locate the
AnyGeneralMuscle in the class tree, and insert a template:

AnyFolder Drivers = {
//---------------------------------
AnyKinEqSimpleDriver ShoulderMotion = {
AnyRevoluteJoint &Jnt = ..Jnts.Shoulder;
DriverPos = {-1.7};
DriverVel = {0.4};
Reaction.Type = {0};
}; // Shoulder driver
//---------------------------------
AnyKinEqSimpleDriver ElbowMotion = {
AnyRevoluteJoint &Jnt = ..Jnts.Elbow;
DriverPos = {1.5};
DriverVel = {0.7};
Reaction.Type = {0};
}; // Elbow driver
}; // Driver folder

AnyGeneralMuscle <ObjectName> = {
//ForceDirection = -1;
AnyKinMeasure &<Insert name0> = <Insert object reference (or full object definition)>;
AnyMuscleModel &<Insert name0> = <Insert object reference (or full object definition)>;
};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 130 of 229

Just as normal muscles, general muscles must be associated with a muscle model. Let us insert a simple one:

AnyMuscleModel <ObjectName> = {
F0 = 0;
};

AnyGeneralMuscle <ObjectName> = {
//ForceDirection = -1.000000;
AnyKinMeasure &<Insert name0> = <Insert object reference (or full object definition)>;
AnyMuscleModel &<Insert name0> = <Insert object reference (or full object definition)>;
};

The empty fields in the muscle model must be filled in:

AnyMuscleModel MusModel = {
F0 = 100.0;
};

We shall associate the muscle with the shoulder joint:

AnyMuscleModel MusModel = {
F0 = 100.0;
};

AnyGeneralMuscle ShoulderTorque = {
//ForceDirection = -1;
AnyKinMeasure &Angle = .Jnts.Shoulder;
AnyMuscleModel &Model = .MusModel;
};

Providing a torque for the shoulder is not enough. We also need a torque in the elbow:

AnyGeneralMuscle ShoulderTorque = {
//ForceDirection = -1;
AnyKinMeasure &Angle = .Jnts.Shoulder;
AnyMuscleModel &Model = .MusModel;
};

AnyGeneralMuscle ElbowTorque = {
//ForceDirection = -1;
AnyKinMeasure &Angle = .Jnts.Elbow;
AnyMuscleModel &Model = .MusModel;
};

Having provided torques for the shoulder and elbow it should be possible to run the inverse dynamic analysis. However, attempting to do so will provide the same
depressing error message as before. The reason is that general muscles share the ability to be unilateral with normal muscles. The direction of action is controlled by the
variable ForceDirection. If the muscle acts in the positive direction of the joint angle, then it direction should be set = 1, and if it is in the negative joint angle direction it
should be -1. In the present case the external load tends to work in the negative angle direction for the shoulder as well as the elbow, and hence the muscles should
counteract in the positive direction:

AnyGeneralMuscle ShoulderTorque = {
ForceDirection = 1;
AnyKinMeasure &Angle = .Jnts.Shoulder;
AnyMuscleModel &Model = .MusModel;
};

AnyGeneralMuscle ElbowTorque = {
ForceDirection = 1;
AnyKinMeasure &Angle = .Jnts.Elbow;
AnyMuscleModel &Model = .MusModel;
};

Now the InverseDynamicAnalysis can be performed. Having done so, we can open a new Chart View and look up the two joint torques as the Fm property of the general
muscles. We can plot both of them simultaneously using an asterix as shown below:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 131 of 229

Notice that in this case we have used the same strength (muscle model) for both joints. However, the maximum joint torque in physiological joints varies a lot. The knee
extension strength, for instance is significantly larger than the elbow extension strength. If you perform this type of modeling you can define joint torque muscles with
strengths comparable to the available joint torque and the system can give you an estimate of how many percent of each joint's strength is used in a given situation. You can
also define different strengths of extension and flexion muscles in a given joint and thereby take for instance the difference in strength in the knee in these two directions
into account.

Another useful property of the general muscles used at joint torque providers is that you can handle closed loops and other statically indeterminate situations, which are not
treatable by traditional inverse dynamics because the equilibrium equations do not have a unique solution. The muscle recruitment algorithm will the distribute the load
between joints according to their individual strengths, and it is therefore important to have reasonable estimates of joint strengths for this type of situation.

Contact and other boundary conditions

One of the characteristics of muscles is that they are unilateral, i.e. they can only exert force in one direction. Mathematically this behavior creates a significant amount of
problems, but many mechanical phenomena have the same characteristics, namely any kind of contact phenomenon. Biomechanics is full of contact problems:

 The contact between a foot and the floor


 The contact between the upper thighs and the seat of a chair
 The contact between two articulating surfaces in a joint.

There is another less appreciated similarity between muscle forces and contact forces: neither is without limit. Muscle forces are obviously limited by the strength of the
muscle. Contact forces to the environment may seem like they are only limited by the strength of whatever is supporting the body, but it can also be limited by friction and
by the pressure on the contacting tissues; if you have a stone in one shoe you will very likely put less weight on that foot than on the other.

So the muscles of the body in addition to creating equilibrium are constrained by the available contact forces to the environment, and these often have different limits in
different directions, typically a high limit in compression perpendicularly against the supporting surface, a smaller limit for friction tangentially to the surface, and no
reaction available in tension. Mathematically and mechanically this is very much how muscles work, and the conditions therefore affect the mechanics of the entire system
much like muscles do and can be mimicked by means of general muscles.

We are going to make a couple of changes to the simple arm model to investigate contact in more detail. We shall imagine that the hand of the model has a vertical wall to
support against. We have to change the kinematics to make the arm slide along the wall. It would be really difficult to figure out which joint angle variations are needed to
make the hand move vertically, so we drive the hand directly instead.

AnyFolder Jnts = {

//---------------------------------
AnyRevoluteJoint Shoulder = {
Axis = z;
AnyRefNode &GroundNode = ..GlobalRef.Shoulder;
AnyRefNode &UpperArmNode = ..Segs.UpperArm.ShoulderNode;
}; // Shoulder joint

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 132 of 229

AnyRevoluteJoint Elbow = {
Axis = z;
AnyRefNode &UpperArmNode = ..Segs.UpperArm.ElbowNode;
AnyRefNode &LowerArmNode = ..Segs.LowerArm.ElbowNode;
}; // Elbow joint

}; // Jnts folder

AnyKinLinear HandPos = {
AnyRefFrame &ref1 = .GlobalRef.Shoulder;
AnyRefFrame &ref2 = .Segs.LowerArm.PalmNode;
};

AnyFolder Drivers = {
AnyKinEqSimpleDriver HandDriver = {
AnyKinLinear &Measure = ..HandPos;
MeasureOrganizer = {0,1};
DriverPos = {0.45, -0.6};
DriverVel = {0, 0.5};
Reaction.Type = {0, 0};
};
/*
//---------------------------------
AnyKinEqSimpleDriver ShoulderMotion = {
AnyRevoluteJoint &Jnt = ..Jnts.Shoulder;
DriverPos = {-1.7};
DriverVel = {0.4};
Reaction.Type = {0};
}; // Shoulder driver

//---------------------------------
AnyKinEqSimpleDriver ElbowMotion = {
AnyRevoluteJoint &Jnt = ..Jnts.Elbow;
DriverPos = {1.5};
DriverVel = {0.7};
Reaction.Type = {0};
}; // Elbow driver
*/
}; // Driver folder

Notice that the previous two joint angle drivers have been disabled. Otherwise the system would become kinematically over-determinate. Notice also that the new driver
drives two degrees of freedom corresponding exactly to the two drivers we have disabled. Finally, please notice the line

Reaction.Type = {0, 0};

This means that the wall presently provides no reaction forces to the arm. Plotting the MaxMuscleActivity provides the following result:

The muscle activity is rather constant which is the natural consequence of the moment arms being rather constant. The gravity as well as the applied load of 100 N are
vertical, so one might be tempted to think that a horizontal support would not make much of a difference. We can do a quick test by simply switching on the horizontal
support of the driver:

Reaction.Type = {1, 0};

This produces immediate proof that mechanics is usually more complicated than expected; even this very simple mechanical system behaves differently from what we
might expect:

Notice that the muscle activity is much smaller in the beginning of the movement with the reaction switched on and much the same towards the end of the movement. It

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 133 of 229

seems like the muscles are able to use the horizontal reaction force to their advantage depending on the posture of the mechanism.

Walls in general do not work like that; they can only provide reaction pressure but no tension. This we can mimic with general a muscle. We first switch the reaction off
again:

Reaction.Type = {0, 0};

Subsequently we define a general muscle:

AnyMuscleModel MusModel = {
F0 = 100.0;
};
AnyMuscleModel ReacModel = {
F0 = 10000.0;
};

AnyGeneralMuscle WallReaction = {
ForceDirection = -1;
AnyKinMeasureOrg Org = {
AnyKinMeasure &wall = ..HandPos;
MeasureOrganizer = {0};
};
AnyMuscleModel &Model = .ReacModel;
};

There are two things to notice here

1. The muscle model for the reaction, ReacModel, is much stronger than the joint muscles. This is because the wall is presumed to be very strong.
2. The ForceDirection property equals -1. This means that the force is working in the opposite direction of the Kinematic measure, i.e. in the negative global x
direction, just like a contact force with the wall would do.

Running the InverseDynamicAnalysis again and plotting the two joint torques provides the following graph (notice they can be plotted simultaneously with the
specification line Main.ArmStudy.Output.Model.*Torque.Fm):

The red curve is the shoulder joint torque, and the green curve is the elbow torque. Notice that the envelope of these two curves is in fact identical to the
MaxMuscleActivity curve we plotted above for the case of no support. You would think that the support would be beneficial in the final stages of the movement where the
arm could rest a bit against the wall. Actually, it is beneficial for the elbow, but the reaction force also increases the torque about the shoulder, and since the shoulder (red
curve) has the higher load of the two, this limits the benefit of the support. Let us see what happens if we turn the reaction force the other way like if the hand could pull
against the far side of the wall:

AnyGeneralMuscle WallReaction = {
ForceDirection = 1;
AnyKinMeasureOrg Org = {
AnyKinMeasure &wall = ..HandPos;
MeasureOrganizer = {0};
};
AnyMuscleModel &Model = .ReacModel;
};

If you run the model again and plot the same graphs, you will see this:

The wall is obviously useful in the initial stages of the movement where the torque generated by the reaction force is in the beneficial direction for both the joints. In the
later stages of the movement the presence of the wall decreases the envelope of the muscle forces slightly, but it has increased the torque in the elbow. The explanation is
that the elbow can increase its action beyond what is necessary to carry the load and generate and additional pressure against the wall, which then decreases the torque in
the shoulder.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 134 of 229

This example shows how complicated the mechanics of the body is: Even this very simplified case would have different solutions if the parameters of the model were
different. For instance if the shoulder were much stronger compared to the elbow, then the elbow would not have been able to help the shoulder in the latter case because
the elbow would have the higher load compared to its strength. On the contrary, the shoulder would have been able to help the elbow in the former case by generating an
additional force pushing against the wall.

This completes the part of this tutorial dealing with muscles. But we are not completely finished yet. The next lesson deals with the important topic of ligament modeling.

Lesson 7: Ligaments
Ligaments are passive structures that connect articulating bones and keep joints assembled. Mechanically they are much like muscles but with no active contractile
element. Ligaments only provide forces when they are stretched by the relative movement of the bones they connect.

This tutorial demonstrates how to define, control, and calibrate ligaments. We need a model to work on. Please download and save the model Demo.Ligament.any . Once
you have stored it on your hard disk, load it into the AnyBody Modeling System and run the SetInitialConditions operation.

As you can see, the model is very simple. The blue structure is an "arm" that extends from the center of the yellow Ground reference frame. It is hinged at the Ground's
origin, and a driver bends it downwards. With the movement, the red ligament is stretched, and a force builds up in it. Try running the InverseDynamicAnalysis operation.
You will see the arm move, and you can subsequently open a Chart View to investigate the results:

As you can see, the ligament force builds up from nothing to about -2000 N as it is stretched. The value is negative by convention because it works in the opposite direction
of the stretching. Notice that the graph has an initial horizontal part. This is because force does not build up until the ligament is stretched beyond its slack length, L0.

Basic mathematical behavior

It looks like the force development is slightly nonlinear. This would make sense because ligament elasticity is generally nonlinear, but in this case it just shows that the
abscissa is not the ligament length but rather an artificial "time" that is proportional to the joint angle.

In the Chart View you can plot any output data against each other. Let's select instead of time the ligament length. Click the "Out" button, and the field containing the
abscissa becomes white. You can now type LigStudy.Output.Model.Lig.Pos" in the abscissa field:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 135 of 229

That's better. Now the elasticity of the ligament is completely linear over the slack length. Let us take a look at the definition of the ligament model:

AnyLigamentModelPol LigModel = {
L0 = 1.30; // Slack length
eps1 = 0.2; // Strain where F1 is valid
F1 = 1000; // Force in the ligament at strain eps1
};

As you can see, we have only defined three properties. L0 is the slack length. The ligament is not stretched until its length goes beyond L0, so its strain is zero at L0. When
the ligament is stretched, it also builds up a force. The rate of force development with stretching can be thought of as the stiffness of the ligament, and it is defined as the
pair (eps1,F1), where F1 is the force in the ligament at strain eps1. Why do we choose to work with strain here rather than absolute length change? The reason is that
ligaments are rather stiff structures, so small length changes can cause large forces, and it is therefore necessary that the slack length fits the model precisely. This length
will usually have to be tuned to size changes of the body model. When we work with strain, the stiffness becomes a more generic property of the ligament and is
independent of the length it gets calibrated to.

The three parameters we have defined leave room for no more than a linearly elastic behavior with a slack length. Ligament elasticity is generally not linear, so we need
something extra to be able to specify nonlinear behavior. The mathematical background for the AnyLigamentModelPol is that it takes the form:

As you can see, it is a fourth order polynomial with the third order term missing. The 0'th order coefficient accounts for the slack length, and the first order coefficient
accounts for the slope when the model is linear and the second and fourth order terms are missing. But in the presence of the nonlinear terms it becomes very difficult to
interpret the significance of each term. For this reason, the nonlinearity in the model is defined by two parameters with an easier interpretation than the above-mentioned
C2 and C4.

The two parameters are called a0 and a1 respectively. The first parameter, a0, defines the slope of the curve at slack length. If you study the curve above, you can see that it
has a sharp kink at the slack length. It changes abruptly from zero slope to the nominal slope given by (eps1,F1). The default value of a0 is 1, and this corresponds to the
slope right after the kink being defined entirely by (eps1,F1). In other words, the curve is pointing directly at the point (eps1,F1). In fact, the significance of the a0 is that it
interpolates the slope between zero (for a0 = 0) and the linear slope you see in the curve above for a0 = 1. Try inserting the following:

AnyLigamentModelPol LigModel = {
L0 = 1.30; // Slack length
eps1 = 0.2; // Strain where F1 is valid
F1 = 1000; // Force in the ligament at strain eps1
a0 = 0.0;
};

Subsequently reload the model, run the InverseDynamicAnalysis, and plot the ligament force again. You will see the following:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 136 of 229

The specification has created a continuous slope of 0 where the curve previously had a kink. Notice that the curve converges back to the "nominal" slope given by the two
points (L0,0) and (eps1,F1)

If you try the following:

AnyLigamentModelPol LigModel = {
L0 = 1.30; // Slack length
eps1 = 0.2; // Strain where F1 is valid
F1 = 1000; // Force in the ligament at strain eps1
a0 = 0.5;
};

- then you get something in between:

The significance of a1 is much the same, except it has its effect at the point (eps1,F1). Rather than at (L0,0). If, for instance you insert this:

AnyLigamentModelPol LigModel = {
L0 = 1.30; // Slack length
eps1 = 0.2; // Strain where F1 is valid
F1 = 1000; // Force in the ligament at strain eps1
a0 = 0.5;
a1 = 0.0;
};

- then you will get a curve that attains zero slope at (eps1,F1):

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 137 of 229

So, a1 = 0.0 corresponds to zero slope, and the default value of a1 = 1.0 corresponds to the slope given by the values of L0, eps1, and F1. You can similarly increase the
slopes by increasing a1:

Unlike normal fourth order polynomials, these curves will continue predictably with no oscillation for as long as desired after (eps1,F1). The reason for this behavior is the
default setting of the parameter

LinRegionOnOff = On

which causes the curve to continue a linear behavior after (eps1,F1). You can, however, obtain the clean fourth order polynomial behavior is you like by switching this
setting off:

AnyLigamentModelPol LigModel = {
L0 = 1.30; // Slack length
eps1 = 0.2; // Strain where F1 is valid
F1 = 1000; // Force in the ligament at strain eps1
a0 = 0.5;
a1 = 1.0;
LinRegionOnOff = Off;
};

Clearly, this causes the curve to diverge after (eps1,F1), which is typical for higher order polynomials Unless you have some special reason for wanting the pure fourth-
order behavior, we recommend that you leave LinRegionOnOff = On.

Calibration

Most ligaments in the body are rather stiff structures in which the force builds up quickly when they are stretched beyond the slack length. This means that a small error in
slack length specification could lead to a large error in computed ligament force. It therefore becomes crucial that the ligaments fit the other parts of the model exactly.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 138 of 229

The easiest way to determine ligament slack lengths is by means of joint angles. For most joints where ligaments play in important role, it is obvious in which position of
the joint the ligament becomes taut. Therefore, ligaments are calibrated just like muscles by positioning the joints in question and letting the system automatically change
L0 of each ligament to the length in that position.

Lets try to calibrate our ligament. The first thing we must do is to create a Calibration Study:

AnyBodyCalibrationStudy LigCali = {
AnyFolder &Model = .LigModel;
nStep = 1;
// This driver puts the joint into the calibration position
AnyKinEqSimpleDriver Position = {
DriverPos = {-pi/4};
DriverVel = {0.0};
AnyRevoluteJoint &Jnt = Main.LigModel.Joint;
};
};

Notice the driver in the study. It positions the joint at the angle of -pi/4. This becomes the position in which the ligament has its slack length. Try loading the model and
then browse your way through the tree to the L0 property of the ligament model:

Double-click it, and its value is shown in the Object Description Window. You should find a value of

Main.LigModel.LigModel.L0 = 1.300000;

This is the slack length of the ligament at load time as defined in the ligament model. Now, run the LigCali.LigamentLengthAdjustment operation, and subsequently
double-click the L0 property again. Now you will see a value of

Main.LigModel.LigModel.L0 = 1.573132;

The system has extended the ligament length a bit to fit the joint angle of -pi/4. Run the InverseDynamicAnalysis study again, and see the influence of the increased slack
length:

You can find the final version of the ligament demo file here .

The mechanical elements


Musculoskeletal modeling is really just an advanced application of the laws of mechanics described by one of the greatest scientists of all times, Sir Isaac Newton, more
than 300 years ago. So the elements of the models you are working on in the AnyBody Modeling system are mostly mechanical in nature, and to use them you must have
sound understanding of the laws of mechanics in general and of Newton's three laws of motion in particular.

The mechanical elements of an AnyBody model are

 Segments
used to represent bones and other rigid elements of models
 Joints
used to connect segments and allow them to articulate with respect to each other
 Drivers
used to specify the movement the model should perform and optionally provide power input as motors
 Kinematic measures
abstraction representation of kinematical constraints

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 139 of 229

 Forces
forces applied to the model

This tutorial also contains a short introduction to inverse dynamics and how it differs from forward dynamics.

This tutorial consists of the following lessons:

 Lesson 1: Segments
 Lesson 2: Joints
 Lesson 3: Drivers
 Lesson 4: Kinematic Measures
 Lesson 5: Forces

Let's head for Lesson 1: Segments .

Lesson 1: Segments
Segments are defined by the AnySeg keyword in AnyScript. They are the rigid bodies on which the system bases its analysis. In a body model, segments are usually bones,
but since an AnyBody model often comprises various equipment and other items, segments are also used to model cranks, pedals, handles, tools, sports equipment, tables,
chairs, and all the other environmental objects a body may be connected to.

In fact, An AnyBody model does not have to entail a living body. You can easily create an AnyBody model of a machine in which no biological elements take part.

Segments in AnyBody are basically a set of mass properties as you can see below.

Segments do not have any particular shape associated with them. By default a segment is originated in its Center of Mass (CoM), but it is possible to move the CoM away
from the origin of the segment's reference frame. The mass properties are defined by means of a mass and an inertia tensor. The segments in the picture above visualize
their mass properties by ellisoids.

Another important property of a segment is that it can have nodes, so-called AnyRefNodes, assigned to it. The connections between the segment and the AnyRefNodes are
rigid, so the nodes move with the segment. The nodes are visualized by the heads of the pins sticking out from the ellipsoids.

A basic definition of a segment could go like this:

AnySeg Potato = {
Mass = 1;
Jii = {0.01, 0.001, 0.01};
AnyDrawSeg drw = {};
};

Notice that the AnyDrawSeg is just an empty pair of braces signifying that we are using the standard settings. This will produce the following image:

The AnyDrawSeg always represents segments as ellipsoids with axis ratios corresponding to the inertia properties. But the AnyDrawSeg class has multiple settings that can
be used to control the appearence of the segment:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 140 of 229

Please refer to the reference manual for further explanation. The Getting Started with AnyScript tutorial provides examples of segment definitions.

Next up is Lesson 2: Joints .

Lesson 2: Joints
You normally think of a joint as something that provides the body with its movement capability. We interpret joints that way because we would not be able to move if our
joints were rigid. But there is also an opposite perception of a joint: as a constraint. If we did not have joints, then our bodies would disconnect into a heap of bones.

The latter perception is how joints really work in AnyBody. Imagine you have two segments with no joints at all. They each have 6 degrees of freedom in space: 3
translations and 3 rotations. So two disjoint segments give us 12 degrees of freedom. If we connect them by a ball and socket joint, then we eliminate 3 degrees of freedom
because they can no longer translate freely with respect to each other, and we are left with a mechanism with 12 - 3 = 9 degrees of freedom. AnyBody will keep rack of all
this for you, but it makes things much easier to understand if you get used to thinking of joints as constraints.

As a final word about perceiving joints as constraints, it might be worth mentioning that these constraints are not taken into account at the moment when you load a model
into AnyBody. By that time, the segments are simply positioned in space where you located them in their definition. In principle, the segments may be in one big,
disorganized heap.

The joint constraints are not imposed until you perform some sort of analysis. Each study has the SetInitialConditions operation for the particular purpose of resolving the
constraints and connecting things. The mathematics of that is a nonlinear system of equations. Such a system may have multiple solutions or no solutions at all. Even if it
has a unique solution, it may de impossible to find. This means that if the segments are too disorganized from their final positions when they are defined, then the system
might not be able to resolve the constraints and put them in their correct positions. The remedy is to define the segments so that their initial positions are not too far away
from the configuration they will have when the constraints are resolved. You can read much more about this subject in the tutorial A study of Studies .

AnyBody provides you with a variety of ways you can connect segments by joints. The class tree reveals the following joint class structure:

The different types are described in detail in the AnyScript Reference manual (Find it in AnyBody->Help of the online version ) . For examples on how to use joints, please
download and study the following two examples:

 Slider crank in 2D
 Slider crank in 3D

The next chapter is Lesson 3: Drivers .

Lesson 3: Drivers
Drivers create movement in a model. They are really functions of time determining the position of a joint or the distance between two points or some other kinematic
measure at any given time through the simulation period.

There are various drivers available to create different types of time dependency. For a demonstration of the different types, please download and study the Driver demo .

Next up is Lesson 4: Kinematic Measures .

Lesson 4: Kinematic Measures


You are not likely to have any sort of idea what a kinematic measure is. Don't worry - you're not supposed to know about it. The concept was invented by AnyBody
Technology as a way of describing dimensions in a kinematic model that you might want to get information about or control with drivers. A joint angle or a distance
between two points are examples of kinematic measures. The position of the center of gravity of the entire model or a subset of its segments are other examples.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 141 of 229

If you define a kinematic measure in your model, then you can study its development. But more importantly you can control it. You can add a driver to a kinematic
measure, and that way control the movement of the mechanism. Such a driver can be added even when the measure is a less tangible quantity like the collective center of
gravity that is not attached to a particular segment.

Joints can be understood as kinematic measures equipped with drivers. For instance, a spherical joint is a distance between two points on two different segments that is
driven to be zero. This means that, using kinematic measures, you can define types of joints that are not available as predefined objects in AnyScript.

Do you remember the simple arm example of the " Getting Started with AnyScript " tutorial? That was a 2-D model of an arm where we produced the movement by
driving the angles of the shoulder and elbow joints directly.

But let us imagine that we wanted the hand to reach out and grab something at a specific position. It would probably be difficult to figure out precisely how to drive the two
joint angles to put the hand in the position we wanted it to attain. Instead, we would want to be able to put the hand (actually the wrist since this simple model has no hand)
directly at the desired position in space and have the elbow and shoulder joints follow implicitly. This is where the kinematic measures come into play. Let's start off with
the model just about where we left in the "Getting Started with AnyScript" tutorial. Please click here to download the necessary file , and save it in some working directory
on your own hard disk.

Let us try initially to create a kinematic measure that will allow us to track the movement of the wrist. To honor the folder structure of the model we shall create a new
folder for the kinematic measure. Let's place it just below the Jnts folder to reflect the kinship between kinematic measures and joints:

}; // Jnts folder
AnyFolder KinematicMeasures = {
AnyKinLinear WristPos = {
// These are the nodes that the measure refers to
AnyFixedRefFrame &Ground = Main.ArmModel.GlobalRef;
AnyRefNode &UpperArmNode = Main.ArmModel.Segs.LowerArm.HandNode;
Ref = 0;
};
}; // KinematicMeasures

An AnyKinLinear is a kinematic measure that gauges the spatial vector between two points. The line Ref = 0 means that the coordinates of this linear distance are
measured in the coordinate system first of the measure's end points which in this case happens to be the global reference frame. For other options, please refer to the
Reference Manual .

So far, we have just added a measure that allows us to track the movement of the hand, but it is still driven by the joint drivers as before. Let's investigate what we have.
Load the model and run a KinematicAnalysis or an InverseDynamicAnalysis, and subsequently open a ChartFX view.

Expanding the tree though Main.ArmModelStudy.Output.Model.KinematicMeasures.WristPos will give you the options shown to the below.

Click Pos, and you will get three graphs tracking the x, y, and z components of the WristPos kinematic measure.

The z component (blue curve) of the measure remains zero throughout the movement because the model is two-dimensional. The top curve (red) is the x component, and
the bottom curve (green) is the y component.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 142 of 229

Now comes the beauty of kinematic measures: Rather than just observing them, you can actually drive them!

We shall replace the existing drivers on the shoulder and elbow joints by drivers on the x and y components of the WristPos kinematic measure.

We need to remove the existing elbow and shoulder drivers to avoid kinematic redundancy. You can enclose the drivers in comment characters /* */, or you can simply
erase them, leaving you with an empty drivers folder:

AnyFolder Drivers = {
}; // Drivers folder

The next step is to fill drivers for the WristPos measure into the Drivers folder. We initially make an empty skeleton. Notice that we are using an AnyKinSimpleDriver
here. If you had measured the hand position by a motion tracking technology and wanted to reproduce the movement, you would probably want to use an interpolation
driver instead.

AnyFolder Drivers = {
AnyKinEqSimpleDriver HandMotionXY = {
};
}; // Drivers folder

We can now fill contents into the HandMotionXY driver that will guide the hand through space:

AnyFolder Drivers = {
AnyKinEqSimpleDriver HandMotionXY = {
AnyKinLinear &Jnt = ..KinematicMeasures.WristPos;
MeasureOrganizer = {0,1};
DriverPos = {0.4,-0.5};
DriverVel = {0.2,0.5};
DriverAcc = {0.0,0.0};
Reaction.Type = {Off,Off}; // The muscles must do the work
};
}; // Drivers folder

The first of the red lines above refers to the WristPos kinematic measure. It simply specifies that this is the measure we want to drive. Notice, however that this measure
has three components, namely the x, y and z coordinates. But we only want to drive two of them. The MeasureOrganizer handles that problem. It lines up the coordinates
of the measure in a row for driving. MeasureOrganizer = {0,1} means that the vectors of driver specifications, such as DriverPos and DriverVel, refer to the x (number 0)
and y (number 1) coordinates of the measure.

The values we suggest for DriverPos and DriverVel have been found by inspection of the graphs depicted above showing the development of the measure coordinates
when we used the shoulder and elbow drivers. This is good practice because it is so easy to specify wrist positions that the arm cannot reach and thereby provoke a
kinematic incompatibility that may be difficult to find in more complex cases.

To conclude, the special feature about kinematic measures is that you can drive them. In AnyBody, you can drive anything that you can measure, and this is really a unique
facility. If something went wrong for you along the way, you can download a commented version of the final result here .

The last lesson in the tutorial on mechanical elements is Lesson 5: Forces .

Lesson 5: Forces
There are several types of forces in an AnyBody model; forces in joints, forces in muscles, and gravity forces working on the segments. This section, however, deals only
with the application of external forces. We need something to work on, and here's a copy of the simple arm model you can use. Please right-click here and save to your
local disk . When you have saved the file, please open it up in AnyBody.

At the end of the ArmModel folder you will find that we have added an empty folder named Loads:

AnyFolder Loads = {

}; // Loads folder
}; // ArmModel

AnyForce3D: External forces

External forces on a mechanical system are usualy perceived as vectors with some point of attack, and this is indeed one of the ways you can define forces in AnyScript.
Let us begin by defining a force acting on the PalmNode of the ForeArm segment. The way to go is to first make sure the model is loaded successfully (by having pressed
F7). Please do not reload the model again before we are finished making the necessary changes.

Place the cursor on the empty line inside the new Loads folder. Then select the Classes tab in the tree view on the left hand side of the editor window, expand the Class List
and scroll down until you come to AnyForce3D. Right-click the class and pick Insert Class Template. This will give you:

AnyFolder Loads = {
AnyForce3D <ObjectName> =
{
//F = {0, 0, 0};
//Flocal = {0, 0, 0};
AnyRefFrame &<Insert name0> = <Insert object reference (or full object definition)>;
};
}; // Loads folder

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 143 of 229

Let us initially give the force a descriptive name:

AnyFolder Loads = {
AnyForce3D PalmLoad = {
//F = {0, 0, 0};
//Flocal = {0, 0, 0};
AnyRefFrame &<Insert name0> = <Insert object reference (or full object definition)>;
};
}; // Loads folder

One of the missing blanks is an AnyRefFrame. This is the point of attack of the force. In our case we want it to work on the PalmNode. We first prepare for inserting the
name of the node:

AnyFolder Loads = {
AnyForce3D PalmLoad = {
//F = {0, 0, 0};
//Flocal = {0, 0, 0};
AnyRefFrame &PointOfAttack = ;
};
}; // Loads folder

Now, please place the cursor just before the semicolon at the end of the PointOfAttack line, select the Model tab in the tree view on the left hand side of the editor
window, unfold the ArmModel.Segs.ForeArm branch, locate the PalmNode, right-click it and select Insert Object Name. You should get the following result:

AnyFolder Loads = {
AnyForce3D PalmLoad = {
//F = {0, 0, 0};
//Flocal = {0, 0, 0};
AnyRefFrame &PointOfAttack = Main.ArmModel.Segs.ForeArm.PalmNode;
};
}; // Loads folder

Please notice now that two lines in the middle of the object are commented out. We need to enable exactly one of them and we shall begin with the first one, specifying
also a non-zero force vector:

AnyFolder Loads = {
AnyForce3D PalmLoad = {
F = {0, -50, 0};
//Flocal = {0, 0, 0};
AnyRefFrame &PointOfAttack = Main.ArmModel.Segs.ForeArm.PalmNode;
};
}; // Loads folder

When this specification is used, the force vector gets defined in global coordinates. The global y direction in this model is upwards, so the vector F = {0, -50, 0} specifies a
load directed downwards. Now is the time to reload the model and open a ModelView window if you have not already done so. After successful load, please select the
InverseDynamicAnalysis and click the Run button. You will see the bulging of the muscles in response to the downward load on the hand.

It may be nice to be able to actually see the force we have applied. This can be done with an AnyDrawVector object that we can conveniently place inside the PalmLoad
object like this:

AnyFolder Loads = {
AnyForce3D PalmLoad = {
F = {0, -50, 0};
//Flocal = {0, -50, 0};
AnyRefFrame &PointOfAttack = Main.ArmModel.Segs.ForeArm.PalmNode;
AnyDrawVector drF = {
Vec = .Fout/200; // Scale the length down
Line = {
Style = Line3DStyleFull;
Thickness = 0.01;
RGB = {1, 0, 0};
End = {
Style = Line3DCapStyleArrow; // This specifies the end to be an arrowhead
RGB = {1, 0, 0};
Thickness = 0.02; // The head begins with twice the thickness of the shaft
Length = 0.05;
};
};

// attach the arrow to the hand


AnyRefFrame &Palm = Main.ArmModel.Segs.ForeArm.PalmNode;
};
};

As you can see, the AnyDrawVec is a class with a lot of different settings available, and there are actually much more than listed here. You get to see all of them if you use
the class tree to insert the object. For now, let's just reload the object and run the model. You should see a red arrow pointing down from the hand indicating the direction of
the force.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 144 of 229

One of the advantages of defining models in a computer language is that numbers can be replaced by mathematical expressions. So instead of the constant force vector we
can write a function of time, for instance:

AnyFolder Loads = {
AnyForce3D PalmLoad = {
F = {0, -50, 0}*sin(2*pi*t);
//Flocal = {0, 0, 0};
AnyRefFrame &PointOfAttack = Main.ArmModel.Segs.ForeArm.PalmNode;
};
}; // Loads folder

If you reload and run the InverseDynamicAnalysis again you will see the force arrow chage direction and you will also see that the muscle activation changes from the
frontal to the posterior side of the arm in response to the changing load.

Let's impose some movement. It is easily done by a small change in the elbow driver:

AnyKinEqSimpleDriver ElbowMotion = {
AnyRevoluteJoint &Jnt = ..Jnts.Elbow;
DriverPos = {1.5};
DriverVel = {60*pi/180};
Reaction.Type = {Off};
}; // Elbow driver

After this change try reloading the model and running the inverse dynamic analysis again. You should see the model flex its elbow.

For the next issue it is better to change the force back to a constant value:

AnyFolder Loads = {
AnyForce3D PalmLoad = {
F = {0, -50, 0};
//Flocal = {0, 0, 0};
AnyRefFrame &PointOfAttack = Main.ArmModel.Segs.ForeArm.PalmNode;
};
}; // Loads folder

Please load and run again and notice how the external force is vertical all the time regardless of the movement of the forearm. This is because we used the property F to
specify the force in the PalmLoad object. How would we go about defining a force that follows the direction of the hand instead? Well, this is what the Flocal property is
for. Let's make a small change in the force specification:

AnyFolder Loads = {
AnyForce3D PalmLoad = {
//F = {0, -50, 0};
Flocal = {0, -50, 0};
AnyRefFrame &PointOfAttack = Main.ArmModel.Segs.ForeArm.PalmNode;
};
}; // Loads folder

The only change here is that we are using the Flocal property rather than F to specify the force. Loading and running the model again will show the force now changind
direction with the movement of the arm but maintaining its direction perpendicular to the forearm, i.e. in the negative y axis of the PalmNode to which it is attached.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 145 of 229

AnyForce: Internal forces (sort of)

Many applications in biomechanics deal with some notion of joint moment. Let us imagine we wanted to apply a given joint moment to the elbow and check how the
muscles would cope with carrying that.

Our first idea might be that the Flocal property of AnyForce3D would be ideal for this. If we just work out the distance between the elbow and the PalmNode then we can
easily compute how much Flocal we have to apply to the forearm to obtain the desired joint moment in the elbow.

But first ideas don't always fly and in this situation the use of AnyForce3D with Flocal would have an undesirable side effect: The applied force would also generate a
moment about the shoulder joint, and since there are bi-articular muscles crossing the shoulder as well as the elbow this is likely to disturb the muscle recruitment pattern
significantly. So, what to do?

Well, what we really want is something that just affects the elbow and is balanced perfectly from the point-of-view of the rest of the model. We could come up with an
applied force that goes from the upper arm to the forearm, and should this force then be perpendicular to the forearm or to the upper arm? Obviously it cannot be both.

It looks like it might be nice with a more general force application option, and this is what the AnyForce class is. It allows us to apply a generalized force to any kinematic
measure we can possibly define. The AnyForce takes the form of the kinematic measure, so a linear measure results in a force and a rotational measure results in a moment.
Moreover, because kinematic measures are such a general concept there are very few limits to the kinds of forces that they can be used to specify. So, the elbow moment
might simply be applied as an AnyForce applied to some rotational measure of the elbow angle, and as the measure we can conveniently use the elbow joint.

We start by disabling the external forces from before:

AnyFolder Loads = {
AnyForce3D PalmLoad = {
//F = {0, -50, 0};
Flocal = {0, 0, 0};

Instead, we define an AnyForce. Place the cursor inside the Loads folder right after the ending brace of the PalmLoad object. Then click the Classes tab in the tree on the
left hand side of the editor window, unfold the Class list, scroll down to the AnyForce class, right-click it and insert a template. You should get this:

AnyFolder Loads = {
AnyForce3D PalmLoad = {
//F = {0, -50, 0};
Flocal = {0, -50, 0};
AnyRefFrame &PointOfAttack = Main.ArmModel.Segs.ForeArm.PalmNode;
AnyDrawVector drF = {
Vec = .Fout/200;
Line = {
Style = Line3DStyleFull;
Thickness = 0.01;
RGB = {1, 0, 0};
End = {
Style = Line3DCapStyleArrow;
RGB = {1, 0, 0};
Thickness = 0.02;
Length = 0.05;
};
};
AnyRefFrame &Palm = Main.ArmModel.Segs.ForeArm.PalmNode;
};
};

AnyForce <ObjectName> =
{
F = ;
//AnyKinMeasure &<Insert name0> = <Insert object reference (or full object definition)>;
};

}; // Loads folder

The structure of the AnyForce class is obviously very simple. This is because it draws so heavily on the kinematic measure inside it for its definition. Let's apply a moment
to the elbow:

AnyForce ElbowMoment = {
F = {-50};
AnyKinMeasure &Elbow = Main.ArmModel.Jnts.Elbow;
};

This applies a moment of -50 units to the elbow. This happens to be an extension moment, so when you load and run the model again, you will notice activity mainly in the

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 146 of 229

flexor muscles. But how did we know that a negative value corresponds to an extension moment? It is actually rather simple. The joint has a positive angle direction and
the applied AnyForce follows the sign convention of the kinematic measure it is attached to. In our case we know from the setting of the driver moving the elbow joint that
a positive angular velocity corresponds to flexion, so a negative moment on the corresponding kinematic measure must be an extension moment.

If you look carefully, you will also see activity in some of the mono-articular shoulder muscles. Why does this happen? Wasn't the AnyForce supposed to only affect the
elbow? Indeed it was and does, but some of the muscles crossing the elbow also affect the shoulder, so co-contraction is necessary to stabilize the shoulder in the presence
of elbow muscle activity.

What makes the AnyForce local, then? The answer is that the AnyForce refers to the elbow joint, and the elbow joint refers to the upper arm and the forearm. So these are
the segments affected by the AnyForce. If the AnyForce includes a reference to a fixed reference frame then the force applied will have a component going to ground and it
will at least partially work as an external force, but otherwise it is strictly internal.

AnyForces have many interesting applications. For instance they can be used to specify gravity-type force fields if you apply them to an AnyCoM measure. Another
interesting use of AnyForces is for specification of predefined muscle forces. There is a kinematic meaure inside any muscle, and if an AnyForce is applied to this measure,
that force will be predefined in the muscle. Please notice, that the system may decide to recruit muscle force beyond what you have applied unless the muscle has been set
to zero strength.

Further studies

The following two examples illustrate more of the features of forces in AnyBody.

1. Demo.Forces.any
2. Demo.AnyForce.any

The first example is a rather basic application of time-varying forces to the aimple arm model. In addition to the subjects covered in the sections above it shows forces
defined directly as interpolated values a set of measured data points, for instance from a force platform.

The second example illustrates among other things how forces acting on a segment can be summed up.

Advanced script features


AnyScript is a powerful programming language designed particularly to make life easy for body modelers. Generality and versatility, however, often come at the cost of
complexity, and there are some advanced topics you must grasp to fully realize the potential of the language. This section presents some of those topics.

This tutorial consists of the following lessons:

 Lesson 1: Using References


 Lesson 2: Using Include Files
 Lesson 3: Mathematical Expressions

We shall begin with Lesson 1: Using references .

Lesson 1: Using References


AnyScript is really a programming language, and just like any other programming language you can define variables and assign values to them. For instance, you may
write

AnyVar a = 10.0;
AnyVar b = a;

Folders are also variables, and a folder definition can go like this:

AnyFolder MyFolder = {
// A whole lot of stuff inside
};

However, folders cannot be assigned like a and b above, so the following is illegal:

AnyFolder MyFolderCopy = MyFolder;

In general, you can only do direct assignment of value variables, i.e. variables containing numbers or collection of numbers. This assignment is allowed:

AnyVector aa = {1,2,3};
AnyVector bb = aa;

But folder assignments are not allowed. So how can you refer to large portions of the model in just one assignment operation? The answer is that you can refer by
reference, and just about any assignment between variables of compatible type will work:

AnyFolder &MyFolderCopy = MyFolder;

The ampersand, '&', in front of the variable name specifies that this is a reference. What it means that MyFolderCopy will just point to MyFolder, so whatever you do to
MyFolderCopy will happen to MyFolder. It is as simple as that. A pointer variable takes up very little space in the computer because it does not copy the data it is pointing
to.

This demo example illustrates some of the important uses of pointer variables: creatingandreferingtoobjects.any

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 147 of 229

Now, let's continue to Lesson 2: Using Include Files .

Lesson 2: Using Include Files


If you have any sort of experience with C or C++ programming, then the concept of include files will be very familiar to you. The idea behind include files is very simple:
You divide one long file into several smaller ones. This is primarily useful, if the division into smaller files is based on some logical principle. Simple as it may be, it
enables some pretty neat model structures that can really help your work.

Usually, the structure of files in a model is such that one file is the main file (containing the Main folder), and the main file contains statements to include other files. An
include file can include other files and so on.

Consider, for instance, the case of one very large AnyScript model. If you have the model in a single .any file, then it may be difficult to locate a particular muscle or
another element that you are looking for. Instead, you could choose to put all the muscle definitions into a separate file. At the position in the main file where you removed
the muscle information, you simply add a statement to include the new muscle file called muscles.any. The statement could look like this:

#include "muscles.any"

Notice the leading # symbol. It signifies that this is a macro statement, and it is the only type of statement in AnyScript that does not require a semicolon in the end. This is
because the statement is not formally a part of the AnyScript language. It is something that is processed before the actual model is parsed.

When the system loads the model and reaches the include statement, it simply reads the include file, and subsequently continues reading the main file. It is a very simple
principle, but it does have some interesting implications:

 You can divide large models into smaller and more manageable chunks
 You can create blocks of data that are easy to re-use in your model. Simply put the data in a file and include that same file several times at different positions in your
the main file. For instance, if you have modeled two arms, you might want to use the same set of muscles for both of them. In that case, create one file containing the
muscles and include it twice.
 You can create libraries of files containing elements you often use in your modeling tasks, and when you build a new model much of the work is accomplished
simply by including the files you have made previously. It is much like constructing models from larger building blocks.

The principle of include files in demonstrated in the following four interconnected files:

 demo.include.any (the main file)


 demo.include2.any
 demo.include3.any
 demo.include4.any

Right-click the files and save them in a directory of your choice. Then start AnyBody and load the main file, demo.include.any.

Next up is Lesson 3: Mathematical Expressions .

Lesson 3: Mathematical Expressions


One of the definite advantages of a modeling language like AnyScript is that mathematical expressions become a natural element in model construction. By means of
mathematical expressions in models you can make the model parametric, enable scaling in various ways, and create dependencies between elements.

In AnyScript you can in principle write a mathematical expression involving variables and references to other objects and to time anywhere in an object definition where
you would otherwise use a number. Furthermore, AnyScript handles scalar numbers, vectors, matrices, and in fact tensors of arbitrary dimensions.

Unlike most programming languages, definition sequence does not have any significance in an AnyScript model. This means that variables can refer to other variables that
are created further down in the model like this:

AnyVar b = a;
AnyVar a = 10;

Instead of the sequence of definition , AnyScript variables depend on the sequence of evaluation . Some expressions are can be evaluated when the model is loaded, while
others have to wait for certain operations to complete. For instance, a muscle force is not known until an InverseDynamicAnalysis operation is performed. The systems
keeps track of when everything is evaluated and will complain if you try to use a variable prematurely.

For instance, kinematic analysis is the first step of an inverse dynamic analysis, so you can make an external force or a muscle strength depend on a position. This is
because forces and muscles strengths are not used until after the kinematic analysis when the positions have been evaluated. However, you cannot make a position depend
on a muscle force because muscle forces are always computed after positions.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 148 of 229

Much of the capability of the mathematical expressions is demonstrated in the example Demo.MathExpressions.any .

Finite element analysis interfacing tutorial

Applications in orthopedic and trauma biomechanics often require information on the internal forces in the body parts. Therefore, frequently Finite Element Analysis
(FEA) is utilized to compute stresses and strains in the tissues.

Essential to get reliable, meaningful results out of this are realistic boundary conditions (BC). Force-wise these BCs are composed from external loadings, dynamic forces
and the corresponding muscle activations for the given situation. As the AnyBody Modeling System (AMS) is capable of providing these forces (an image visualizing this
is shown to the below) it seems to be straight forward to use this data as input to a FEA.

A typical workflow of such FEA with loads estimated by AnyBody is summarized in the figure below. Typically, a surface and a volume model is created based on
medical images (CT or MRI scans) using image processing and segmentation methods available in various software packages. Based on the volume model, a FE model can
be generated. In this tutorial, we shall assume that you are familiar with methods for segmentation and FE mesh-generation and we shall focus on how to transfer computed
forces from the AMS to the FE code.

Based on the segmented bone surface, also used to generate the FE mesh, one can derive parameters used to scale the generic AnyBody model for a suitable fit the actual
scanned subject. It is also beyond the scope of this tutorial to consider these details, but let us just notice that this can be done at many different levels of accuracy
depending on the resources and data available. An STL file from the segmentation of the bone can be useful in this process and scaling can be done, for instance, based on
bony landmarks of the bone. The STL file can also be imported into AnyBody model for visualization, but this alone will not change the musculoskeletal system if you
don’t change the model definition). Please refer to the tutorial on Scaling for details on this matter.

A registration of the coordinate system used in the FE mesh, i.e., the scanned configuration, to the coordinate system of the bone in AnyBody is naturally needed for

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 149 of 229

transferring the load data properly. We shall just touch briefly upon this issue, showing how you can deal with different coordinate systems. However, the examples, you
find in the lessons of this tutorial, are typically using FE meshes based on geometries from the generic AnyBody models in AMMR; thus, scaling and registration is not a
relevant issue.

The boundary conditions consist of the applied loads (exported from AnyBody) and fixation conditions. The loads exported from AnyBody should include all loads on the
bones, including reactions to applied external and muscle loads, i.e. the joint loads and this should in principle be sufficient for loading the FE model. The exported loads
do provide a situation of equilibrium between all forces in the AnyBody model; however, this includes all inertia forces as well and these is not easily to apply to a FE
model of a bone. The bone is just a part of a segment in the rigid-body concept in AnyBody models, where the segment inertia also includes the soft tissues surrounding the
bone. Neglecting parts of the inertia in FE bone model and maybe all accelerations, we will not have a situation of equilibrium. Therefore, we need to apply proper fixation
BCs to accommodate for this. This will also remove issues of singular stiffness matrix, in standard static analyses.

In the following tutorial, it is shown how AnyBody can be used to analyze the stress state of bones. In the first lesson, the built-in facilities of AnyBody to generate output
for a FEA are explained in general. A simple example is included, which shows all the steps from the AnyBody application to the nice colored Finite Element stress plots.
We will briefly go through the following steps:
• Generate a force output file from AnyBody
• Export the bone surface from AnyBody
• Mesh the bone
• Apply material description and boundary conditions
• Solve the Finite Element Model

In the first showcase freely available software is used to generate the mesh and solve the problem. Therefore, also users without access to a commercial FEA software
package can step through it. But obviously there are plenty of possibilities on the market to do FEA and this example should just illustrate the flow of the task, without
claiming to do high-end FEA.

The following lessons consider interfaces to selected commercial FE packages, Ansys and Abaqus. In these cases, small interface tools are applied to automatically convert
the standard load output file from AnyBody to formats directly readable by the FE packages.

Now it's time for Lesson 1: Export of data for FEA.

Lesson 1: Export of data for FEA

In this example we want to shed some light on an important issue for all aquarium owners: What’s the magnitude of stress in the lumbar vertebra L5 during lifting of a 10
kg aquarium?

First we need a model to work on.

With the AnyBody Modeling System you already have a repository of models available, for details please see the AnyBody Assistant available from the menu. This tutorial
has been written using the AnyBody Managed Model Repository Ver. 1.2 (AMMRV1.2) if you see differences between the tutorial text and your own results please
download AMMRV1.2 from www.anybodytech.com/anybody.html?fwd=modelrepository

The starting point for this tutorial is the model: Applications/Examples/StandingLiftFEA/StandingLiftFEA.main.any

Please find the model and load it by pushing F7 and open a Model View. You should see something similar to the picture to the right. The vertebral body we want to
analyze is marked with a circle on the zoomed-in picture.

This model is based on the “StandingLift” model of the AMMR Repository. It is a full body model lifting a box of 10 kg and therefore also imposing forces on the spine. In
this tutorial we will be using a more basic representation of the L5 vertebra than the one included in the repository model. Our tutorial model lacks the pedicles and facets
joints, consisting just of the vertebral body. This is done in order to simplify the FEA related processes which will be discussed later.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 150 of 229

Another simplification will be that we only use the model with joint generating muscles; this will keep the force output files small. In order to export the forces acting on
the vertebra we have to include the corresponding output function. Place your cursor inside the Study folder of the main file. Open the Classes tab in the tree view on the
left side of the editor window and locate the AnyMechOutPutFileForceExport class. Right-click it and insert the class template:

AnyBodyStudy Study = {
AnyFolder &Model = .Model;
InverseDynamics.Criterion.Type = MR_MinMaxStrict;
tStart = 0.5;
tEnd = 0.5;
Gravity = {0.0001, -9.81, 0.0001};
nStep = 1;

AnyMechOutputFileForceExport <ObjectName> =
{
FileName = "";
/*NumberFormat =
{
Digits = 15;
Width = 22;
Style = ScientificNumber;
FormatStr = "";
};*/
//AllSegmentsInStudyOnOff = Off;
AnyValue/*Use a AnyValue-derived class*/ <Insert name0> = <Insert value or expression>;
//AnyValue/*Use a AnyValue-derived class*/ <Insert name1> = <Insert value or expression>;
//AnySeg &<Insert name0> = <Insert object reference (or full object definition)>;
};

};

Next we have to fill in the necessary information.

AnyMechOutputFileForceExport FEAoutput =
{
FileName = "FEAoutput.txt";
/*NumberFormat =
{
Digits = 15;
Width = 22;
Style = ScientificNumber;
FormatStr = "";
};*/
AllSegmentsInStudyOnOff = Off;
AnySeg &L5Seg = Main.HumanModel.BodyModel.Trunk.SegmentsLumbar.L5Seg;
};

The AllSegmentsInStudyOnOff switch decides if only the forces of the listed segments will be exported or data from all segments in the study. Usually you will only use a
selected amount of data to keep the file manageable. The following segment points to the L5 segment which is the one we like to analyze. You can fill in the path by
browsing the Model tab to the L5 segment, right-click it and choose “Insert Object Name” in the drop down menu.
That’s all you have to do for the force export. Please reload the model by pressing F7. Open the Study tree in the Operation tab in the left side of the main window and
choose “InverseDynamicsAnalysis”. Press the “Run” button. The model will analyze one timestep and write the FEAoutput.txt file which we have specified before. Let’s
have a closer look on the Output file. It is located inside your Application folder. You can open it either directly in AnyBody or in any text editor of your choice.

===================== Start of time-step =====================

TimeSample[0]:

t=5.000000000000000e-001;

Segment[0]:

Name=Main.HumanModel.BodyModel.Trunk.SegmentsLumbar.L5Seg;

m=2.085000000000000e+000;

Jmatrix=1.168885000000000e-003,-9.570149999999998e-004,0.000000000000000e+000;-9.570149999999998e-004,6.423084999999999e-
003,0.000000000000000e+000;0.000000000000000e+000,0.000000000000000e+000,6.591969999999999e-003;

r=-4.191723282427327e-002;1.143386931706198e+000;-1.497737038225964e-004;

rDot=5.893342512209260e-003;2.446813630010483e-004;1.925491094541430e-004;

Omega=1.062708497851127e-002;1.762864022916421e-003;-5.853096975772747e-003;

rDDot=-1.156661004595328e-002;-4.599319370658593e-004;-5.426105181307061e-003;

OmegaDot=-2.994499467387653e-001;-4.974436887280604e-002;9.364055661513510e-003;

Forces(17):

Force[0]:

Name=Main.HumanModel.BodyModel.Trunk.JointMuscles.L5SacrumJnt.Extension.dof0.Muscle.PosMuscle;

Class=AnyMainFolder.AnyFolder.AnyFolder.AnyFolder.AnyFolder.AnyFolder.AnyFolder.AnyFolder.AnyFolder.AnyGeneralMuscle;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 151 of 229

SegmentName=Main.HumanModel.BodyModel.Trunk.SegmentsLumbar.L5Seg;

SegmentID=0;

Pos=1.077503778883285e-003;1.138342420959186e+000;-7.537109318454295e-005;

RefFrame=Main.HumanModel.BodyModel.Trunk.SegmentsLumbar.L5Seg.L5SacrumJntNode;

Components(1):

F[0]=0.000000000000000e+000;0.000000000000000e+000;0.000000000000000e+000;

M[0]=-1.587641435713052e-002;5.682776806642225e-001;7.224660293361494e+001;

...

It starts with information on the included segment. All the geometrical entries are listed. One nice feature here is that all coordinates stated in this file are given in the same
(global) coordinate system. In the following all forces acting on the segment are listed. In this case one of the artificial joint moment generating muscles is shown. The
position of the force is given as well as all of its components from AnyBody. Depending on the nature of the underlying AnyForce class, which you can see in the “Class”
entry, there are a different number of forces and moments listed. An AnyForce may have any number of components, which may be a physical force or a torque, but it may
also be a more generalized load, not measured in Newton or Newton-meter. Basically these force components are related to the underlying kinematic measure, so that force
times kinematic displacement becomes work/energy; in other words the kinematic measure decides the unit of the force component. Anyway, these occasionally somewhat
artificial force measures present in the AnyBody model are converted to real point forces and point torques, when outputted to the AnyFE output file. Therefore, we find F
[i] and M[i] in the AnyFE, which are the point force and the point torque associated the i 'th component of the given AnyForce object. The total force acting in the global
direction at a point can be found by simply adding all the components forces, i.e. summing F[i] for all i at that location.

In many cases, the components are indeed simple such that component i=0 for instance is Fx as could be expected, but since this Fx may refer to a local coordinate system
of a particular segment, a joint attachment node, or the like, F[i] and M[i] may still have three non-zero values when exported to the AnyFE file. This is because the data is
tansformed while being exported so that the AnyFE is referring to a single coordinate system for all of the exported data; this system is often (by default) the global
coordinate system or it can be a local coordinate system.

Let us have a look at the following entry which basically gives the joint constraints in the L5-Sacrum joint:

Force[12]:

Name=Main.HumanModel.BodyModel.Trunk.JointsLumbar.L5SacrumJnt.Constraints.Reaction;

Class=AnyMainFolder.AnyFolder.AnyFolder.AnyFolder.AnyFolder.AnySphericalJoint.AnyKinEq.AnyReacForce;

SegmentName=Main.HumanModel.BodyModel.Trunk.SegmentsLumbar.L5Seg;

SegmentID=0;

Pos=1.077503778883285e-003;1.138342420959186e+000;-7.537109318454295e-005;

RefFrame=Main.HumanModel.BodyModel.Trunk.SegmentsLumbar.L5Seg.L5SacrumJntNode;

Components(3):

F[0]=1.401363916972399e+001;4.096147301511706e-001;2.002355876380579e-004;

M[0]=0.000000000000000e+000;0.000000000000000e+000;0.000000000000000e+000;

F[1]=-1.375600406291832e+001;4.706177494369769e+002;-1.423747832550264e+000;

M[1]=0.000000000000000e+000;0.000000000000000e+000;0.000000000000000e+000;

F[2]=-1.455818281740253e-004;4.287178778727723e-003;1.418527218321406e+000;

M[2]=0.000000000000000e+000;0.000000000000000e+000;0.000000000000000e+000;

You can see the three moments have zero entries. This is due to the fact that this joint is discretized as a spherical joint which therefore cannot take up moments. In the
same manner all other joints are handled.

Next we need an object where we can apply our exported forces. This is also quite simple. A facility is built in the system (from Version 3.1) which allows the export of
all .anysurf and .stl geometries from your application in the .stl format. The function will export the geometry in its actual position, so please make sure that your model has
not been reloaded since the force export otherwise run the InverseDynamicAnalysis again to bring it to right position. Of course it also involves all scaling which has been
applied to the bones. Browse through the model tree to the L5Seg (Main\HumanModel\BodyModel\Trunk\SegmentsLumbar\L5Seg) in order to export the L5 segment.
Inside this folder you find the DrawSTL folder. Right-click the folder and choose “Export Surface”. Choose a convenient place to store the file and give it the name
“L5.stl”. A dialog box will appear which allows you to specify a scale value for the output file. The scaling can be useful to switch from one units system to another. In our
case we have m as units in the AMS, but want to have mm for the FE geometry. So choose as scale factor 1000. From the AnyBody point of view, that’s all we have to do.
Please note that not all bones which are right now in the Repository may be suitable for a FEA. As the main intention is to have graphical representation of the body it may
appear that some bone are simply to coarse for a detailed analysis. But of course you are free to import your own .stl file into the AnyBody Modeling System to substitute
existing bones. You will have to tweak your CAD file a bit in order to make it fit. Donation of better quality CAD files of bones to the models is most welcome.

Based on the exported forces and .stl file we can now build and analyze a FE model. Below we shall build an FE model applying the loads and other boundary conditions
manually using non-commercially available software. However please notice that in the following lessons, we consider more smooth integration with selected commercial
software by means of small converter software tools provided by AnyBody Technology. These tools automatically convert the AnyFE output file from AnyBody to input
files for the particular FE software.

After building a FE model based on this data the internal stress in the bone tissue can be evaluated. Below are some von-Mises stress plots showing approximately the

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 152 of 229

middle cross section of the vertebral body.

With a stress level of approx. 0.5 MPa in the cancellous bone we are pretty far away from the yield strength, so we can conclude that it appears to be ok for aquarium
owners to lift their pets in an aquarium of this size.
But of course we did some generous shortcuts to achieve this goal and neglected a lot of detail which is provided by the AnyBody Modeling System.

Building the FE-model

In this section a short description of how to build a Finite Element model using AnyBody data is given. If you are an experienced FE user you may want to skip this
section.
As this should be by no means a Finite Element tutorial we will use some shortcuts to achieve our goal: We already restricted the analyses to one time step. Further, we will
only take the joint reaction forces into account. How one can handle muscle forces will be discussed below. And finally the used geometry was simplified. Basically only
the vertebral body is used. The main reason for this is to avoid getting lost in the jungle of meshing.

In the following, we will make use of two freely available tools. Preprocessing (meshing and applying boundary conditions) is done using IA-FEMesh provided by the
University of Iowa. Calculix is used as solver and post-processor. This fine piece of software is written and maintained by Guido Dhondt and Klaus Wittig. Calculix v1.8
and IA-FEMesh v1.0 are used in this tutorial. So things may slightly change with updates on the programs. Please note that neither of these programs is in related to
AnyBody Technology.

Please follow the links shown above, download and install the two programs if you want to do some hands-on FEA.

Building the model - preprocessing

A file with the finished model is provided below, in case you do not want to go through the entire model building process.
Open IA-FEMesh and press the “Surface” tab to load your (earlier exported) .stl file. After successful loading we have to define a building block. The building block is a
prerequisite to the mesh generation and its surfaces will be meshed and further projected on the bone. For reasons of simplicity it has been prepared. Please press the
“Block” tab and chose “Load”. Browse to the folder “FEA” which is inside the “StandingLiftFE” application folder. Choose the file “L5_block.vtk”. Some boxes around
the vertebral body will appear.

In the next step, we will have a look at the local mesh density and mesh the structure.
Press the “Mesh” tab and choose “Assign/Edit Mesh Seeds”. By activating the “Color Code Mesh Seeds” you can review the settings for the mesh density which was set in
the predefined block. Just click on the different wireframes and see the number of divisions per line. The density is slightly increased in the regions of the vertebral
endplates.

Next is to generate the actual mesh. Open again the “Mesh” tab and press “Create”. Fill in “n” for node label and “e” for element label, make sure that the volumetric mesh
is chosen and the “perform smoothing" option is checked. “Apply” will generate a nicely meshed vertebral body (right)

After this we have to assign material properties to the elements. Go to the “Materials” tab and select “User-Defined”. You can simply give in the Young’s modulus for the
whole set of elements and the Poisson’s ratio. Reasonable values may be an average 1000 (MPa) for the modulus and 0.3 for the ratio. But of course you may also want to
model the bone in more detail, separating the cortical shell and the cancellous bone or even base the material properties on density data. But this is surely not within the

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 153 of 229

scope of this tutorial.


In this example we will apply only the joint forces on the endplates. Therefore we will not make explicit use of all the information given by the AnyBody force export file.

We have to select two node sets to apply the boundary condition. This is done by pressing the “Load/BC” tab and the “STEP-Load/BC Assignments” choose “Node Set
Definition” and use the appearing tools to define the node sets on both endplates. You should use the option “Visible surface nodes” and the + and – tool to select the set.
You have to hold the Ctrl button to select nodes and confirm your selection by right clicking on the selected nodes. (In this case it is a rather good approximation to select
just a set of nodes on the endplates as force application points. This may not be so easy for other cases; in these the given information on the coordinates of the forces is
essential to apply the force in the right way.)

After the definition of a node set on both endplates we have to provide the boundary conditions. For this we need our force export file. Please open the file (it should be
located in your StandingLiftFEA application folder) in an editor and scroll down to Force[12]. This force is the joint reaction on the L5-Sacrum joint.

Force[12]:
Name=Main.HumanModel.BodyModel.Trunk.JointsLumbar.L5SacrumJnt.Constraints.Reaction
Class=AnyMainFolder.AnyFolder.AnyFolder.AnyFolder.AnyFolder.AnySphericalJoint.AnyKinEq.AnyReacForce
Segment=Main.HumanModel.BodyModel.Trunk.SegmentsLumbar.L5Seg
SegmentID=0
Pos=1.077503784652309e-003;1.138342420959032e+000;-7.537109341625460e-005;
RefFrame=Main.HumanModel.BodyModel.Trunk.SegmentsLumbar.L5Seg.L5SacrumJntNode
NumComponents=3
F[0]=1.401363929748741e+001;4.096147338026376e-001;2.002355902030428e-004;
M[0]=0.000000000000000e+000;0.000000000000000e+000;0.000000000000000e+000;
F[1]=-1.375600406286652e+001;4.706177495305955e+002;-1.423747837481083e+000;
M[1]=0.000000000000000e+000;0.000000000000000e+000;0.000000000000000e+000;
F[2]=-1.455818161773931e-004;4.287178425936316e-003;1.418527096959978e+000;
M[2]=0.000000000000000e+000;0.000000000000000e+000;0.000000000000000e+000;

By summing up the rows for the forces F[0], F[1], and F[2] we get the resulting components for the joint reaction load. This can be directly used in the force definition as
they are given in the same coordinate system. In this case only the Y-force component is of interest as all other forces are pretty small. Choose “Force” and your defined
node set for the lower endplate. Specify the Y-force to 471 (N). Make sure to confirm with “Apply”. Select the node-set on the opposite endplate and set the displacement
to be 0 in all direction, confirm again with “Apply”. (Next also the moment generating muscles could be taken into account in a similar manner, but this will be skipped
here.)
The model is now finished. Now we have to export the model. This export can be found under “Load/BC”. Choose “Export ABAQUS File”. This will write an ABAQUS
style input file for a FE-Solver. This is the format Calculix can read. Press “Apply” and name the file “L5FEA” and save.
There is one more thing that has to be defined preliminary to the FEA - the desired output. Please open a text editor and load the L5FEA.inp file. In this file the whole
analysis is defined, using a reference to the node and elements file.

**=========================================================================
** HISTORY DATA **
**=========================================================================
**------------------------------------------------------------STEP 1
*STEP, INC=100, NLGEOM=YES, UNSYMM=YES
*STATIC
1.0, 1.0
**
*BOUNDARY, OP=NEW
unten, 1, 1, 0
unten, 2, 2, 0
unten, 3, 3, 0
**
*CLOAD
EndplateB, 2, 2.2488
**
**------- Output Requests --->
**

*NODE FILE

*EL FILE

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 154 of 229

S,

**
**
**
*END STEP

Please include the Output Requests (see red lines above). This will make sure we get some results to look at. Save the file and close the editor.

Solve and postprocessing

If you have somehow screwed up your model or simply didn’t want to go through the model building process, you can find a working model here:
StandingLiftFEA\FEA\L5FEABackup.inp. (In this model also different materials for the cortical shell (E = 12000 MPa) and the cancellous bone structure (E = 200 MPa)
have been assigned.

If you want to use this model instead of your own build, please change the following comments involving”L5FEA” to “L5FEABackup”.)
Open up the Calculix command shell and browse to the directory where you placed the L5FEA.inp file. Now type

ccx L5FEA

and press return. This will push the model forward to the solver and start the analysis. Within a few seconds a nice JOB FINISHED should appear. Now, let’s have look at
the results: Therefore, type

cgx L5FEA.frd

This will call the Calculix (pre- and) postprocessor. A graphical window showing the vertebrae will appear. Clicking on the left side will give you a panel to visualize the
results. First you have to choose the dataset you want to access. For example click on Datasets>Stress to activate the stress dataset. After this you can choose the desired
Entry, e.g. Mises Stress. You can assess the results in more detail using different Viewing settings (Please have a look at the Calculix help file for more information on
this). Here are two examples for the von-Mises stresses in the middle of the cross section of the vertebral body:

This completes Lesson 1.

In the following lessons, we show somewhat more automatic interfaces to selected commercial FE packages using small interface tools

Click here to continue to

· Lesson 2: ANSYS interface .

· Lesson 3: ABAQUS interface

Lesson 2: ANSYS interface

This chapter shows how to use AnyBody features to apply boundary conditions to a Finite Element Model generated in ANSYS. This is current work in progress; we
assume the workflow will be even smoother in the future. You need an additional add-on to the AnyBody Modeling System to run this tutorial. This is needed to convert
the AnyBody output to ANSYS APDL code. Please get it from http://www.anybodytech.com/download.html?did=FEtools.overview .

The model we will have a look at is a clavicle midshaft fracture. We will analyze the muscle forces acting on the clavicle during lifting his arm and analyze the stress in the
implant. The standard Standing model taken from the AMMRV1.1 will be used. The basic general workflow is shown the figure below.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 155 of 229

Here we will focus on the link between AnyBody and ANSYS. So we assume we have a “ready to go” Finite Element model which basically only lacks its boundary
conditions. (This model could be e.g. generated from medical image data. The AnyBody model has to be scaled to fit to the actual case (it can be beneficial to import
the .stl file of the bone in question into the AMS to scale the model accordingly. Please note, the bone will not actually change the musculoskeletal system if you don’t
change the model definition). Please refer to scaling tutorial for details on this matter.)

In this tutorial we will use a bone derived from a standard scaled AnyBody model, so no scaling has to be applied here.

Let’s start with the AnyBody part. We have to make sure the two models in the two systems are aligned. The idea is to include local reference frames in both systems
which will be used for all further data transfer. Open the Standing model from the AMMRV1.1, or better make a copy of the whole model folder and use this one. For
convenience we will reduce the model detail by excluding the left arm and switching off the muscles in all body parts, except the right arm. This is done in the
BodyPartsSetup.any file. Next we define the local ref frame on the clavicle. All forces will be later exported with respect to this coordinate system. You can either use a
pre-defined reference system in the AMS or create a new one. The following lines create a new node located in the Sternoclavicular joint:

AnySeg &RiArm = Main.HumanModel.BodyModel.Right.ShoulderArm.Seg.Clavicula;


RiArm ={AnyRefNode localrefframe={
sRel = {0,0,0};
// ARel = RotMat(0.5*pi,x);
AnyDrawRefFrame drws = {ScaleXYZ = {1,1,1}*0.3;RGB={0,0,1};};
};

Include them e.g. in the Environment file. After reload of the model the reference frame is shown

Next, we have to define the same local coordinate system in the ANSYS model. Download the prepared ANSYS file here and save it in your working directory. In the
Mechanical APDL (ANSYS) environment (ANSYS Classic), a simple way to do so is to modify the location of the work plane. Once the work plane is in place create a
local coordinate system at the workplane origin and give it the number 1000. (In fact you can give it any number, but we have to refer to the coordinate system later, so we
have to know its name). Load the clavicular_base.db in the Mechanical APDL (ANSYS) environment and have a look.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 156 of 229

This shows the clavicle model, which contains a midshaft fracture, modeled with a reduced stiffness and treated with a plate fixation.

Next we want to analyze the forces in the AMS. Change the Mannequin file to create the desired motion. We want to analyze a simple lifting case, so all we specify is
flexion in the shoulder joint. Open the Mannequin file and look for the PostureVel folder. Change the Glenohumeral flexion value to 150/Main.Study.tEnd, this determines
the joint velocity necessary to reach 150 degree flexion taking into account the simulation time.

AnyFolder Right = {
//Arm
AnyVar SternoClavicularProtraction=0; //This value is not used for initial position
AnyVar SternoClavicularElevation=0; //This value is not used for initial position
AnyVar SternoClavicularAxialRotation=0; //This value is not used for initial position

AnyVar GlenohumeralFlexion =150/Main.Study.tEnd;

We also want to alter the initial starting position for the motion, enter the Posture position folder and make the changes indicated below.

AnyFolder Right = {
//Arm
AnyVar SternoClavicularProtraction=-23; //This value is not used for initial position
AnyVar SternoClavicularElevation=11.5; //This value is not used for initial position
AnyVar SternoClavicularAxialRotation=-20; //This value is not used for initial position

AnyVar GlenohumeralFlexion =0;


AnyVar GlenohumeralAbduction = 7;
AnyVar GlenohumeralExternalRotation = 0;

AnyVar ElbowFlexion = 5.0;


AnyVar ElbowPronation = -60.0;

We want this motion to be done in 10 seconds and analyze 5 time steps. This can be set in the main file. Search the Study folder and change the end time of the study to 10
seconds and the number of time steps to 5.

AnyBodyStudy Study = {
AnyFolder &Model = .Model;

tEnd = 10.0;
Gravity = {0.0, -9.81, 0.0};
nStep = 5;

Now we have to specify which forces we want to export to the FE model. For this we make use of the Class inserter. Place you cursor in the Study folder in the main file,
below the code shown above and select the Classes tab on the left side of the main file window. Search for the class named AnyMechOutputFileForceExport right click on
it and choose Insert class template. This will insert the class necessary for force export.

AnyMechOutputFileForceExport <ObjectName> =
{
FileName = "";
/*NumberFormat =
{
Digits = 15;
Width = 22;
Style = ScientificNumber;
FormatStr = "";
};*/
//UseRefFrameOnOff = Off;
//AllSegmentsInStudyOnOff = Off;
//XMLformatOnOff = Off;
//AnyRefFrame &<Insert name0> = <Insert object reference (or full object definition)>; You can make any number of these objects!
//AnySeg &<Insert name0> = <Insert object reference (or full object definition)>; You can make any number of these objects!
};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 157 of 229

Create a folder in your Standing model folder named files_in and one called files_out. This will be used to store the FE files. Change the class as shown below. These
definitions specify that all forces acting on the segment Clavicula will be written in the xml file clavload. The UseRefFrameOnOff option allows giving a reference frame
in which all forces are reported. Switch the option on and name the ref frame (the one we created before). You can find the path to the ref frame by browsing the model tree
on the left side of the main file window to the right clavicle and right click Insert object name.

AnyMechOutputFileForceExport FE_out =
{
FileName = "files_in/clavload.xml";
UseRefFrameOnOff = On;
AnyRefFrame &ref1 = Main.HumanModel.BodyModel.Right.ShoulderArm.Seg.Clavicula.localrefframe;
AllSegmentsInStudyOnOff = Off;
XMLformatOnOff = On;
//AllSegmentsInStudyOnOff = Off;
AnySeg &clav = Main.HumanModel.BodyModel.Right.ShoulderArm.Seg.Clavicula;
};

This class will write all the muscle and joint forces for all time steps in one xml file. Please create a folder names “files_in” in your Application folder. We need one more
step to convert the xml file to ANSYS APDL language. An additional add-on to the AnyBody Modeling System is necessary to do so. This tool is available at
http://www.anybodytech.com/download.html?did=FEtools.overview . Save the files in your model folder. In these files, an executable is included that will translate the xml
code to APDL and a template for the APDL specification. You can call this code either by a shell prompt or from inside AnyBody. You can use the class
AnyOperationShellExec for this. The names for the executable, its working directory and the options for the call of the exe file have to be given. The options specify the
input file (-i) and the output file folder (-o). The –t option gives a template for the APDL conversion. Please adjust the path corresponding to your setup and insert this code
below the study folder:

AnyOperationShellExec ConvertToAPDL={
Show=On;
FileName = "AnyFE2APDL.exe";
Arguments = "-i ..\files_in\clavload.xml -o ..\files_out -t ..\APDLTemplate.txt";
WorkDir="C:\Users\sd.ANYBODY\TEMP\AMMRV1.2\AMMRV1.2\Application\Examples\StandingModel\Converter";
};

The basic procedure of the conversion is:

· Create local coordinate systems for each muscle insertion and joint point

· Apply forces to the points

· Create beam connections between the force application points and the bone surface

Let’s have a closer look at the APDL template. Open the APDLTemplate.txt file in a text editor. It is structured in three sections, a head string, a tail string and a final
string. The first string contains basic definitions, the second applies the forces and creates the beam connections for each force point, the third gives some solution options
and a solve command. The file is created in a way that it assumes the local coordinate name in which all forces are given is named 1000, and the material numbers of
implant and fracture are between 50 and 60. The template can be altered to fit to your actual problem. One thing you have to change right now is the path to your FE
model.

RESUME,'clav_base','db','C:\Users\sd.ANYBODY\TEMP\Clavicle_paper\FE\',0,0

Please include the path to your model.

Now we are ready to run the analysis and convert the data. Reload the model in the AMS. Select RunApplication in the Operations tree. This will automatically run the
Calibration and InverseDynamics studies. Next select ConvertToAPDL and run it. This will create 5 files in the files_out folder written in APDL language.

Open ANSYS Mechanical Utility and read the input of each individual file with File-Read input from. This will load the model, apply the boundary conditions and start to
solve. Once finished post-process the results.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 158 of 229

Alternatively you can run all models in one go by reading in the outputfileList file. Each loadstep will be written in a new result file. You can look at the results by loading
them one on one in the post-processor.

Lesson 3: Abaqus interface

This chapter shows how forces calculated in AnyBody can be applied as boundary conditions to a FE Models generated for Abaqus.

Below you see the flowchart from the introduction of this tutorial extended with a converter step that converts the AnyFE output file to a format readable by Abaqus. This
step is carried out by a small tool, called AnyFE2Abaqus.exe, which is available at http://www.anybodytech.com/download.html?did=FEtools.overview .

The model we will have a look at is a model of the claviclebone. We will analyze the muscle forces acting on the clavicle during lifting an arm and compute the stresses in
the bone. The standard Standing model taken from the AMMR will be used (Notice, this tutorial was authored with AMMRV1.3.1. It should run equally well with newer
versions of the AMMR, but the results may vary due to updates of the models).

We shall focus on the interfacing between AnyBody and Abaqus and therefore we will use a bone mesh derived from the standard scaled (=un-scaled) AnyBody model.
Thereby, we can skip the step to do any scaling according to the subject data and in particular the bone geometry. This would have been needed if the bone model was
derived from scanned data coming from another, significantly different, person than generic AnyBody model.

Let’s start with the AnyBody model. We have to make sure the FE and AnyBody models are aligned. The idea is to include local reference frames in both systems which
will be used for all further data transfer. Open the Standing model from the AMMR, or better make a copy of the whole model folder and use this one. For convenience we
will reduce the model detail by excluding the left arm and switching off the muscles in all body parts, except the right arm. This is done in the BodyPartsSetup.any file.

Next we define the local ref frame on the clavicle. All forces will be later exported with respect to this coordinate system. You can either use a pre-defined reference
system in the AMS or create a new one. The following lines create a new node located in the Sternoclavicular joint:

AnySeg &RiArm = Main.HumanModel.BodyModel.Right.ShoulderArm.Seg.Clavicula;


RiArm ={
AnyRefNode localrefframe={
sRel = {0,0,0};
// ARel = RotMat(0.5*pi,x);
AnyDrawRefFrame drws = {ScaleXYZ = {1,1,1}*0.3;RGB={0,0,1};};
};
};

Include them e.g. in the Environment file. After reload of the model the reference frame is shown

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 159 of 229

Download the prepared Abaqus file here and save it in your working directory. Please note that this FE model of clavicle was created in the same reference frame as the
clavicle model in the AnyBody model, since we have actually used the STL exported from AMMR for this bone. Therefore, 'localrefframe' does not have to be displaced in
order to match with the coordinate system of the FE mesh, but had the FE mesh been generated based on scanned data, the registration between AnyBody model's clavicle
and the FE mesh can be entered using 'localrefframe''s sRel and Arel members.

In a similar manner one could define a local reference frame in Abaqus by means of the *SYSTEM keyword; however, this is not advisable because the AnyFE Converter
does not handle the *SYSTEM keyword in the supplied mesh file. We shall return to the issue of aligning the coordinate systems for the AnyBody forces and the mesh
later, and so far we consider 'localrefframe' to be aligned with the mesh coordinate system.

This figure above shows the clavicle bone mesh used for this example. This bone is modeled with a reduced stiffness, which can be interpreted as an osteoporotic bone.

Next we want to analyze the behavior of the bone subjected to the forces computed in the AMS. First, change the Mannequin file to create the desired physical activity. We
want to analyze a simple lifting case, so all we specify is flexion in the shoulder joint. Open the Mannequin file and look for the PostureVel folder. Change the
Glenohumeral flexion value to 50/Main.Study.tEnd, this determines the joint velocity necessary to reach 50 degree flexion taking into account the simulation time.

AnyFolder Right = {
//Arm
AnyVar SternoClavicularProtraction=0; //This value is not used for initial position
AnyVar SternoClavicularElevation=0; //This value is not used for initial position
AnyVar SternoClavicularAxialRotation=0; //This value is not used for initial position

AnyVar GlenohumeralFlexion =50/Main.Study.tEnd;

We also want to alter the initial starting position for the motion, enter the Posture position folder and make the changes indicated below.

AnyFolder Right = {
//Arm
AnyVar SternoClavicularProtraction=-23; //This value is not used for initial position
AnyVar SternoClavicularElevation=11.5; //This value is not used for initial position
AnyVar SternoClavicularAxialRotation=-20; //This value is not used for initial position

AnyVar GlenohumeralFlexion =0;


AnyVar GlenohumeralAbduction = 7;
AnyVar GlenohumeralExternalRotation = 0;

AnyVar ElbowFlexion = 5.0;


AnyVar ElbowPronation = -20.0;

We want this motion to be done in 10 seconds and analyze 5 time steps. This is set in the main file. Search the Study folder and change the end time of the study to 10
seconds and the number of time steps to 5.

AnyBodyStudy Study = {
AnyFolder &Model = .Model;

tEnd = 10.0;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 160 of 229

Gravity = {0.0, -9.81, 0.0};


nStep = 5;

Now we have to specify which forces we want to export to the FE model. For this we make use of the Class inserter. Place you cursor in the Study folder in the main file,
below the code shown above and select the Classes tab on the left side of the main file window. Search for the class named AnyMechOutputFileForceExport right click on
it and choose Insert class template. This will insert the class necessary for force export.

AnyMechOutputFileForceExport <ObjectName> =
{
FileName = "";
/*NumberFormat =
{
Digits = 15;
Width = 22;
Style = ScientificNumber;
FormatStr = "";
};*/
//UseRefFrameOnOff = Off;
//AllSegmentsInStudyOnOff = Off;
//XMLformatOnOff = Off;
//AnyRefFrame &<Insert name0> = <Insert object reference (or full object definition)>; You can make any number of these objects!
//AnySeg &<Insert name0> = <Insert object reference (or full object definition)>; You can make any number of these objects!
};

Create a folder in your Standing model folder named files_in and one called files_out. This will be used to store the FE files. Change the FE_out object as shown below.
These definitions specify that all forces acting on the segment Clavicula will be written in the xml file clavload. It is important to use the xml format, since the AnyFE
converter only reads this format.

The UseRefFrameOnOff option enables specification of a reference frame in which all forces and positions are reported. Switch this option on and name the ref frame (the
one we created before). You can find the path to the ref frame by browsing the model tree on the left side of the main file window to the right clavicle and right click Insert
object name.

AnyMechOutputFileForceExport FE_out =
{
FileName = "files_in/clavload.xml";
UseRefFrameOnOff = On;
AnyRefFrame &ref1 = Main.HumanModel.BodyModel.Right.ShoulderArm.Seg.Clavicula.localrefframe;
AllSegmentsInStudyOnOff = Off;
XMLformatOnOff = On;
//AllSegmentsInStudyOnOff = Off;
AnySeg &clav = Main.HumanModel.BodyModel.Right.ShoulderArm.Seg.Clavicula;
};

This object will write all the muscle and joint forces for all time steps in one xml file.

We are now ready to execute the AnyFE converter and transform the generic AnyFE XML file to an Abaqus readable INP file. The AneFE converter tool is available at
http://www.anybodytech.com/download.html?did=FEtools.overview . Unpack the files in your model folder. These files include the AnyFE converter, which is an
executable called AnyFE2Abq.exe. It can convert the xml code to Abaqus keyword sequence and combine it with the FE model.

The AnyFE converter is a command line tool with options controlled by program arguments. Running the program with the –h , i.e. AnyFE2Abq.exe –h . We shall briefly
go through the important options here.

The –i and –o options specify the input AnyFE xml file ( -i ) and the output file ( -o ), respectively. The –m option is used to specify a FE model without boundary
conditions . This Abaqus INP file, containing the mesh only, will be included in the converter output INP file by means of an include-statement.

Another significant option is –e , which is the radius of muscle/ligament attachment area. This radius (default value is 1 cm) is used for the construction of coupling
constraint between a loaded point and the surface of the bone. Please note that this radius is used on all loads applied, not only muscles and ligaments, but also joint
reactions, applied loads, etc. This parameter is not a physiological parameter. Please also note that in case of complex concave geometries these constraints may select
wrong parts of the bone surface and may require some manual adjustment.

You can call the converter either from a shell prompt or from inside the AnyBody system. The latter can be done by using the following class: AnyOperationShellExec.
The names for the executable, its working directory and the options for the call of the exe file have to be given. Please adjust the path corresponding to your setup and
insert this code below the study folder:

AnyOperationShellExec ConvertToAbq={
Show=On;
FileName = "AnyFE2Abq.exe";
Arguments = "-i ..\files_in\clavload.xml -o ..\files_out\output.inp -m .\clavicula.inp";
WorkDir=".\ ";
};

This will enter an operation called ' ConvertToAbq' into the model and running this will execute the AnyFE converter. From the shell prompt you write the following to get
the same result:

AnyFE2Abq.exe -i ..\files_in\clavload.xml -o ..\files_out\output.inp -m .\clavicula.inp

At this point, let us return to the issue of the coordinate systems that we have used so far and an alternative option. In the example we have exported all the positions and
forces with reference to a given manually defined system attached to the clavicle, i.e. the 'localrefframe'. The AnyFE converter will by default will transfer all positions and

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 161 of 229

forces directly, i.e., in the same coordinate system as exported the AnyFE XML file. In the above, we have therefore considered 'localrefframe' to be the coordinate system
of the FE model, which is also the CT/MRI scan system. Notice that in the given case, the segment reference and the output reference are aligned since the FE mesh was
based on the original bone geometry from the AnyBody model, i.e. sRel = {0, 0, 0}.

As an alternatively, you can export the AnyFE XML file in another reference frame, even the global system in AnyBody (UseRefFrameOnOff=Off) for that matter. This
implies that the data of the AnyFE XML file may or may not contain motion of the bone and it will probably.not be aligned with the FE mesh/CT/MRI scan system. If you
chose this an option, the AnyFE Converter can remove the rigid body motion by using the –r option equal to 'segment':

AnyFE2Abq.exe -i ..\files_in\clavload.xml -o ..\files_out\output.inp -m .\clavicula.inp –r segment

This makes all AnyFE data from the AnyFE Converter being transformed to the local frame of the segment, here the clavicle segment, before applied to the FE model and
outputted.

If the reference frame of the segment is not identical to the one of the FE mesh, one can apply a constant transformation to all data accommodating for this misalignment.
The –t option allows you to enter the transformation as a string containing space separated numbers. The command line will look like:

AnyFE2Abq.exe -i ..\files_in\clavload.xml -o ..\files_out\output.inp -m .\clavicula.inp –r segment –t "a11 a12 a13 a21 a22 a23 a31 a32 a33 dx dy dz"

The transformation may contain either 9 or 12 numbers. The first nine, aij, must be the orthogonal rotational transformation matrix and the latter optional three, dx, dy, and
dz, are the translations.

These options allow you to handle the coordinate systems differences using the AnyFE Converter, i.e., outside AnyBody. For instance this implies that you do not have to
redo simulations just to apply the same forces to another FE mesh with another local frame; this can all be done with adjustment of the parameters for the AnyFE converter.

Now we have looked at how to execute the AnyFE converter properly, so let us have a look at what it does.

Please notice that the AnyFE Converter is reading Abaqus input file (INP) and it is only expecting a simple mesh specification. This reader is not fully compatible with the
INP keyword language for Abaqus. Basically, it only reads in the first block of nodes (*NODE section) and it does not accept commands that may interfere with the
interpretation of this node section. This implies that many Abaqus keywords are not allowed in front of the first node section. This also implies that subsequent node
sections are not read and therefore, not used for application of forces.

The AnyFE Converter performs the following actions:

· Maps all AnyBody exported forces, i.e., joint reactions, muscle forces and applied forces to the provided FE mesh. Mass related forces are neglected, i.e.,
gravitational and acceleration equivalent forces.

o Defines nodes in the positions from the AnyFE output file, i.e. the position of all loads (this includes muscle /ligament attachment nodes)

o Defines amplitudes for each force/moment component in the AnyFE output file

o Defines concentrated loads (*CLOAD) in each of these nodes

o Defines coupling constraints between the created nodes and a part of the surface of the bone

· The mesh in included

· Adds inertia relief loads (*INERTIA RELIEF)

Please note that the inertia relief loads will automatically be added to the model in order to provide a full set of boundary conditions. However, these loads require a density
value in the material definition section. Absence of this density value will result in the error during the FE analysis. In case when additional constraints are present in the
model, e.g. environment support, contact with another bone, etc., the inertia loads can be suppressed or removed.

Now we are ready to run the analysis and convert the data. Reload the model in the AMS. Select RunApplication in the Operations tree. This will automatically run the
Calibration and InverseDynamics studies. Next select ConvertToAbq operation and run it. This will create a new Abaqus input file in the files_out folder.

Open Abaqus and import the input file from the output directory. This will load the clavicle mesh model, apply the boundary conditions. Next step is to make your custom
final adjustments, run the FE solver, and when finished, post-process the results. The image below shows the results of running the model without any custom adjustments,
however in the following we shall consider modification of the load application regions.

On the following picture, you can see the muscle attachments nodes and coupling constraints that are applied to the finite element model.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 162 of 229

Bear in mind that the muscle attachment area is considered to have a constant radius, however, in many cases these areas are elongated and have irregular pattern. Let us
assume that the area for the sternocleidomastoid muscle has to be changed to fit better the user’s expectations, for example, to be more physiological. That can be done by
defining the desired muscle attachment area as a new surface in the FE model and changing the relevant coupling constraint to refer to this surface. In our example, we
create a surface on the posteriormedial side of the clavicle as it shown on the following pictures. Please note that you will also need to set the influence radius option to ´To
outermost point of the region´ in order to make sure that you now make the coupling to the whole surface.

The following picture shows how the modified constraint looks like; the sternocleidomastoid muscle attachment patch is now spread on the surface elements of the clavicle
mesh.

We can run the solver again and inspect the results, see the image below. In the crude model, we have worked with in this case, we do not see significant changes due to the
modification in the overall picture.

Building block tutorial

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 163 of 229

Developing accurate models of the human body is an enormous task, and it is not something each user can do from scratch. We all have to rely on models other people
have made, and if we keep improving and exchanging them, we shall end up with a very good supply of models that fit most purposes. The AnyBody Managed Model
Repository is an attempt to provide such a library.

These are some of the tasks you will want to accomplish with predefined models:

 To change the model pieces to fit your own purposes - preferably without tampering with the interior workings of the parts you are using.
 To be able to combine existing body parts to larger models.
 To be able to attach the parts you can find to model bits you construct yourself.

All this can be done very elegantly in the AnyScript language provided you keep it in mind when you construct your models. The AnyBody Model Repository is
constructed that way, and it contains numerous examples of the technique. In short, it uses the following elements of the language to make it happen:

1. Include files
2. Parameters
3. Equipping parts with their own interfaces

While there are many different ways models could be constructed to obtain the modularity we are looking for, the AnyScript Model Repository represents one very well-
structured solution, and AnyBody Technology strongly recommends following the structure of this library when new models are developed.

The Repository Model Structure

The model repository is really not a part of the AnyBody Modeling System. It is a library of models that scientists and other advanced users have developed and made
available in the public domain. The AnyBody Modeling System does not require you to structure your models in any particular way. But it is much easier to manage large
models if you divide them into logical parts, and if you follow the structure of the Repository, then you can use the body parts in the Repository for your own models.

So this tutorial is an introduction to the Model Repository structure as well as a case in point of how models can be organized and interfaced with each other in general.

The Repository has its files structured into two main groups:

Application contains the various devices, environments and working situations you may want to hook the body up to. An application could be a model lifting a box,
walking, or riding a bicycle. This means that the Application branch is where you can find the main files of models you can analyze, i.e. the files you actually load into the
AnyBody Modeling System. You will know them because they have "Main" in their names: <application name>.Main.any.

Body contains AnyScript models of the body with no attachments and no specification of movement, forces, or supports. The entire body model contains many hundred
muscles and it is rather heavy computationally. For this reason the Body directory is structured to enable the user to link applications to subsets of the body model such as
the lower extremities or the shoulder model.

The idea behind the division into Application and Body is that each user wants to model the human body in a special situation. This can take place in the Application
branch with references to the Body branch but without tampering with the more delicate Body parts at all.

Let us stay with the Body branch for just a moment. The initial models were created by the AnyBody Research Group from Aalborg, Denmark, but from a rather early
stage in the development, other groups of model developers chipped in. So the Body branch is divided into separate parts where each group of developers can keep their
own models:

AAUHuman contains the Aalborg full body model, while AUHuman contains a mandible model developed in Århus, and Beta refers to other research groups and the non-
human models. When you develop an application you can choose to link to whatever body model is your favorite or even choose to generate your own. You may also copy
the models of another group into a separate directory and introduce the changes you favor into it.

Body modeling is challenging because so much data is involved, so most users will - at least initially - prefer to link to the body models that are already in the Body branch.
This means that the user will create an application in the Application directory that links to a number of model parts in the Body directory. The Application directory has
also its internal structure:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 164 of 229

Within each of the subdirectories in Application you will find different type of applications, the Examples folder as its name indicates is the main content with a lot of
examples of applications, then you will find a folder with validation studies and the Beta folder contains the non-human applications. This is the kind of applications you
can find in Examples:

You can find more information on the structuring of the individual body part files in the Structure lesson .

In the rest of this tutorial we shall consider the situation where a new application is to be built using body parts from the Aalborg branch of Body. We shall do so using two
different strategies of increasing complexity:

1. When an existing application is similar enough to what you want to do to form the basis of the new application.
2. When a new application is constructed using a custom set of body part.

This tutorial is based on version 8 of the AnyScript model repository. Please notice that the repository models are subject to frequent updates and that a newer, better, and
possibly slightly incompatible version may be available from the homepage of the AnyBody Research Project . Also the demo models provided in the AnyBody Modeling
System may be updated compared to the version used here.

With the AnyBody Modeling System you already have a repository of models available, for details please see the AnyBody Assistant available from the menu. This tutorial
has been written using the AnyBody Managed Model Repository Ver. 1.1 (AMMRV1.1) if you see differences between the tutorial text and your own results please
download AMMRV1.1 from http://forge.anyscript.org/gf/project/ammr/frs/

With that done, please proceed to lesson 1: Modification of an existing application .

Lesson 1: Modification of an existing application

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 165 of 229

The Application branch of the repository contains a large amount of applications where different collections of body parts are hooked up to more or less complicated
environments. Some of these environments may be extremely simple, such as a floor to stand on, while others may be mechanisms in their own right such as wheel chairs
or bicycles with complicated crank mechanisms. In the vast majority of cases, the easiest way to develop a new application is to find a similar existing application, copy it,
and modify it to suit your purpose. This is what we shall do in this initial lesson of the building block tutorial.

The standing model

The Examples branch of the Application part of the repository contains a number of versions of standing models. These models are useful as starting points for many
applications comprising the entire body. In the following we shall perform two modifications of a static standing model that will transform it to a dynamic model operating
a hand-driven pump.

The first step is to go to Application/Examples and locate the directory called StandingModel. Make a copy of the directory and rename the copy to HandPump (or
HandPumpTutorial. If you are working on the full version of the repository, there might be a HandPump model already. This model originates from the one from this
tutorial). Then go into the new HandPump directory, locate the file named StandingModel.Main.any and rename it to HandPump.Main.any. Then double-click the
HandPump.main.any file to open it in the AnyBody Modeling System, and we are ready to go.

Before starting to modify the model, time may be invested well in familiarization with its basic structure. The standing model was originally created as an AnyBody-
parallel to so-called digital manikins. It is a model whose posture is controlled by a set of anatomical joint angles specified in the file mannequin.any. If you browse down a
little bit into the main file you will come to the following section:

//This file contains joint angles which are used at load time
// for setting the initial positions
#include "Mannequin.any"

// This file contains the exact same joint variables as the mannequin
// file but their values are obtained from the model
// once the kinematic analysis has been done
#include "MannequinValuesFromModel.any"

AnyFolder ModelEnvironmentConnection = {
#include "JointsAndDrivers.any"
};

Double-clicking the line with "Mannequin.any" will open up the mannequin file. Browsing a little down the file will show this:

AnyFolder Mannequin = {

AnyFolder Posture = {
//This controls the position of the pelvi wrt. to the global reference frame

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 166 of 229

AnyVar PelvisPosX=0.046;
AnyVar PelvisPosY=1.16;
AnyVar PelvisPosZ=0;
//This controls the rotation of the pelvis wrt. to the global reference frame
AnyVar PelvisRotX=0;
AnyVar PelvisRotY=0;
AnyVar PelvisRotZ=0;

// These variables control the rotation of the thorax wrt the


// pelvis
AnyVar PelvisThoraxFlexion=0;
AnyVar PelvisThoraxLateralBending=0;
AnyVar PelvisThoraxRotation=0;

AnyVar NeckExtension=0;

AnyFolder Right = {
//Arm
AnyVar SternoClavicularProtraction=-23; //This value is not used for initial position
AnyVar SternoClavicularElevation=11.5; //This value is not used for initial position
AnyVar SternoClavicularAxialRotation=-20; //This value is not used for initial position

AnyVar GlenohumeralFlexion =-0;


AnyVar GlenohumeralAbduction = 10;
AnyVar GlenohumeralExternalRotation = 0;

AnyVar ElbowFlexion = 0.01;


AnyVar ElbowPronation = -20.0;

AnyVar WristFlexion =0;


AnyVar WristAbduction =0;

AnyVar HipFlexion = 0.0;


AnyVar HipAbduction = 5.0;
AnyVar HipExternalRotation = 0.0;

AnyVar KneeFlexion = 0.0;

AnyVar AnklePlantarFlexion =0.0;


AnyVar AnkleEversion =0.0;

AnyVar SubTalarEversion =0.0;


};

AnyFolder Left = {

This first section of the mannequin file contains the folder Posture of which you can only see a subset in the code above. The posture folder lets you specify anatomical
joint angles in degrees, and when you subsequently load and run the model it will assume the posture you have specified. The bottom part of the mannequin file contains
this folder:

AnyFolder Load = {
AnyVec3 TopVertebra = {0.000, 0.000, 0.000};

AnyFolder Right = {
AnyVec3 Shoulder = {0.000, 0.000, 0.000};
AnyVec3 Elbow = {0.000, 0.000, 0.000};
AnyVec3 Hand = {0.000, 0.000, 0.000};
AnyVec3 Hip = {0.000, 0.000, 0.000};
AnyVec3 Knee = {0.000, 0.000, 0.000};
AnyVec3 Ankle = {0.000, 0.000, 0.000};
};
AnyFolder Left = {
AnyVec3 Shoulder = {0.000, 0.000, 0.000};
AnyVec3 Elbow = {0.000, 0.000, 0.000};
AnyVec3 Hand = {0.000, 0.000, 0.000};
AnyVec3 Hip = {0.000, 0.000, 0.000};
AnyVec3 Knee = {0.000, 0.000, 0.000};
AnyVec3 Ankle = {0.000, 0.000, 0.000};
};
}; // Loads

This is a set of three dimensional vectors that allow you to apply external loads to various predefined points on the model.

The model has an additional feature concerning its posture control: The ankle angle values in the mannequin.any file are not used. The reason is that the model contains a
balancing condition that requires it to keep its total center of mass directly above the global z axis on which the ankle points are also placed. To enable the model to
accommodate the balance condition it must have some degree of freedom to adjust the center of mass, and this is done via the ankle joints.

With these basic properties of the model in mind, let us proceed to Lesson 2 in which we shall give the model something to hold on to.

Lesson 2: Adding a segment


The first step of building the hand pump model is to add a segment which will eventually become the hand wheel driving the pump. Start by opening the
HandPump.Main.any file in AnyBody. In the main file you can toggle between different versions of the body model and it can be advantageous to select a light version
while building the model. This will allow us to get the model up and running without spending a lot of time on reloads. To do so we will use a body model without
muscles. A bit down in the main file you will find the following:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 167 of 229

AnyFolder HumanModel = {

AnyFolder &Mannequin=.Model.Mannequin;

// Select the body model:


// ----------------------
// This file contains a list of all body parts, select them to create
// the body model wanted.
#include "BodyPartsSetup.any"

// This file creates the body model from the selected list.
#include "..\..\..\Body\AAUHuman\BodyModels\GenericBodyModel\BodyModel.any"

Double click on the line "BodyPartsSetup.any" to open the file. This is the file controlling the construction of the body. We will get back to it in detail in lesson 6 , for the
moment we will only remove the muscles of our body. Please make the following modifications:

// Trunk: 1 included, 0 not included


// *********************************
#define TRUNK 1
// This is just the bones,
// Choose one of the following options to add muscles
#define TRUNK_SIMPLE_MUSCLES 0

// RightArm: 1 included, 0 not included


// ************************************
#define RIGHT_ARM 1
// This is just the bones,
// Choose one of the following options to add muscles
#define RIGHT_ARM_SIMPLE_MUSCLE 0
#define RIGHT_ARM_SIMPLE_MUSCLE_ONLY_ON_NECK 0
#define RIGHT_ARM_MUS_3E 0

// LeftArm: 1 included, 0 not included


// ***********************************
#define LEFT_ARM 1
// This is just the bones,
// Choose one of the following options to add muscles
#define LEFT_ARM_SIMPLE_MUSCLES 0
#define LEFT_ARM_SIMPLE_MUSCLES_ONLY_ON_NECK 0
#define LEFT_ARM_MUS_3E 0

// RightLeg: 1 included, 0 not included


// ************************************
#define RIGHT_LEG 1
// This is just the bones,
// Choose one of the following options to add muscles
#define RIGHT_LEG_SIMPLE_MUSCLES 0
#define RIGHT_LEG_MUS_3E 0

// LeftLeg: 1 included, 0 not included


// ***********************************
#define LEFT_LEG 1
// This is just the bones,
// Choose one of the following options to add muscles
#define LEFT_LEG_SIMPLE_MUSCLES 0
#define LEFT_LEG_MUS_3E 0

Then load the model by pressing F7.

Before we add the wheel segment, let us spend just a few moments considering where to place it. The file structure of the application looks like this:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 168 of 229

These files are organized according to the principle that the model is divided into three parts:

1. The model parts concerned with the human body. These are imported from the Body part of the repository.
2. The model parts concerned with the environment. These are the parts that are modeled bottom-up for each new application.
3. A section connecting the body parts to the environment.

The wheel we are about to add is not a part of the human body. It logically belongs to the model's environment, and these parts are defined in the Environment.any file.
Please open Environment.any:

AnyFolder EnvironmentModel = {

/* **********************************************************
This folder contains the definition of the Environment
- GlobalRefFrame

********************************************************** */

AnyFixedRefFrame GlobalRef = {
Origin ={0.0,0.0,0.0};
#include "drawcoorsystem.any"
AnyDrawRefFrame drw={};

};//GlobalRef
};

As you can see, it is extremely simple containing only a global reference frame, which in this model plays the role of a floor to stand on. We shall add a hand wheel to the
model, but first we shall define a point on the global reference frame about which the hand wheel will eventually revolve:

AnyFolder EnvironmentModel = {

/* **********************************************************
This folder contains the definition of the Environment
- GlobalRefFrame

********************************************************** */

AnyFixedRefFrame GlobalRef = {
Origin ={0.0,0.0,0.0};
#include "drawcoorsystem.any"
AnyDrawRefFrame drw={};

AnyRefNode Hub = {
sRel = {0.4, 1.4, 0.0};
AnyDrawNode drw = {};
};
};//GlobalRef
};

When you reload the model and open a Model View Window you will see that a point has appeared in the form of a little grey ball in front of the chest. The next step is to
define the wheel:

Place the cursor just below the definition of GlobalRef. Go to the Class Tab in the left pane Editor Window; unfold the class list and find AnySeg. Right-click the class and
insert a class template. You will obtain this:

AnyFixedRefFrame GlobalRef = {
Origin ={0.0,0.0,0.0};
#include "drawcoorsystem.any"
AnyDrawRefFrame drw={};

AnyRefNode Hub = {
sRel = {0.4, 1.4, 0.0};
AnyDrawNode drw = {};
};
};//GlobalRef

AnySeg <ObjectName> =
{
//r0 = {0, 0, 0};
//rDot0 = {0, 0, 0};
//Axes0 = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 169 of 229

//omega0 = {0, 0, 0};


Mass = 0;
Jii = {0, 0, 0};
//Jij = {0, 0, 0};
//sCoM = {0, 0, 0};
};

We fill in the blanks and add a draw segment:

AnySeg Wheel = {
r0 = .GlobalRef.Hub.sRel;
Mass = 5;
Jii = {0.003, 0.003, 0.3};
AnyDrawSeg drw = {};
};

Notice that we have given the wheel mass properties that cause the draw segment to take on a wheel shape. We shall also add two points to the wheel that can subsequently
function as handles:

AnySeg Wheel = {
r0 = .GlobalRef.Hub.sRel;
Mass = 5;
Jii = {0.003, 0.003, 0.3};
AnyRefNode rHandle = {
sRel = {0.2, 0, 0.1};
};
AnyRefNode lHandle = {
sRel = {-0.2, 0, -0.1};
};
AnyDrawSeg drw = {};
};

Next we fix the wheel segment to the hub node by means of a revolute joint (notice that every time a new object is inserted it can be done from the Classes tree):

AnySeg Wheel = {
r0 = .GlobalRef.Hub.sRel;
Mass = 5;
Jii = {0.003, 0.003, 0.3};
AnyRefNode rHandle = {
sRel = {0.2, 0, 0.1};
};
AnyRefNode lHandle = {
sRel = {-0.2, 0, -0.1};
};
AnyDrawSeg drw = {};
};

AnyRevoluteJoint WheelHub = {
AnyRefFrame &Hub = .GlobalRef.Hub;
AnyRefFrame &Wheel = .Wheel;
Axis = z;
};

Finally, let us define a driver to make the wheel rotate:

AnyRevoluteJoint WheelHub = {
AnyRefFrame &Hub = .GlobalRef.Hub;
AnyRefFrame &Wheel = .Wheel;
Axis = z;
};
AnyKinEqSimpleDriver WheelTurn = {
AnyRevoluteJoint &Hub = .WheelHub;
DriverVel = {-pi};
};

The model has now gone from being static to moving and to see it move we must increase the number of time steps in the model. This happens in the study section of the
Main file:

AnyBodyStudy Study = {
AnyFolder &Model = .Model;

tEnd = 1.0;
Gravity = {0.0, -9.81, 0.0};
nStep = 10;

}; // End of study

Please reload the model and run the kinematic analysis. You should see the wheel turning half a round.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 170 of 229

Here's some emergency help if you are having problems making the model work: HandPump.2.zip contains the three modified files from this lesson.

The next step is to hook the hands up to the handles and get the arms moving in Lesson 3: Kinematics .

Lesson 3: Kinematics
So far we have added a revolving segment - a hand wheel - to the standing model. In this lesson we shall deal with the kinematics in the sense that we are hooking the hand
up to the handles on the wheel. This will make the arms move with the wheel as it turns and it is a convenient and simple way of realizing what would otherwise be a rather
complex movement.

Before we begin it is worth noticing that we did a successful kinematic analysis at the end of the preceding lesson. This shows us that the model is kinematically
determinate, so there is a balance between joint degrees of freedom and constraints in the model. So now that we wish to add constraints by hooking the hands up to the
handles we must remove a similar number of the existing constraints. Otherwise the model will have redundant and mutually incompatible kinematic constraints and refuse
to move or even assemble.

The model's arms are currently driven by:

 three joint angles in the shoulder (the gleno-humeral joint)


 one joint angle in the elbow
 one pronation angle of the forearm
 two joint angles in the wrist

If we attach a hand to a handle by a spherical joint we will be adding three constraints to the model, and we must correspondingly remove three of the constraints
mentioned above. We cannot just remove three random constraints. For instance, we know that the model is going to have a variation of the elbow angle, so we cannot
leave the model with a specification of constant elbow angle. We also know that shoulder flexion and extension is going to vary through the movement. That will account
for the second degree of freedom. Finally, when the elbow is flexed and the hand is holding on to the handle, shoulder internal and external rotation is impossible. So that
constraint will also have to be removed.

Let us begin by defining the spherical joint between the right hand and the handle. If you unfold the model tree in the left-hand side of the editor window, then you can
come obtain the following:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 171 of 229

At the very bottom of this tree you find a glove segment as well as a hand. The glove is a remedy for the fact that we have a rigid hand in the model. Rigid segments are
infinitely strong, and when you attach something very strong to the environment you can sometimes get unreasonable results. So we have added an extra glove segment to
the hand. The connection between the hand and the glove has a finite strength that emulates the grip strength of a normal hand. This means that by attaching stuff to the
glove rather than to the hand we eliminate the potential problem of the model abusing the strong hand.

The natural position of this joint would be in the JointsAndDrivers.any file, because that is where we put the elements that connect the body to the environment. If you
open this file you will see that it has a folder called Drivers that implements the joint angles specified in the mannequin file. But there is not a Joints folder. This is because
the standing model does not have any actual joints with the environment. So we go to the top of the file and create a new folder for joints:

AnyFolder Joints = {

};

AnyFolder Drivers = {

We are going to make two spherical joints. The easiest way to do it is to create the first one with the object inserter and then copy it to make the second one. Place the
cursor on the empty line between the two braces of the new Joints folder, pick the Classes tab, and unfold the class tree to locate the AnySphericalJoint. Right-click and
insert a template:

AnyFolder Joints = {
AnySphericalJoint <ObjectName> =
{
AnyRefFrame &<Insert name0> = <Insert object reference (or full object definition)>;
AnyRefFrame &<Insert name1> = <Insert object reference (or full object definition)>;
};

};

We first define the necessary local names:

AnyFolder Joints = {
AnySphericalJoint rhHandle = {
AnyRefFrame &Glove = <Insert object reference (or full object definition)>;
AnyRefFrame &Handle = <Insert object reference (or full object definition)>;
};
};

The next step is to specify the two reference frames to be joined. In this case the two frames will be the glove of the right hand and the right handle. Both of these can be
located in the object tree provided the model is loaded. Click the Model tab and expand the tree through the HumanModel, BodyModel, Right, an down to the Glove
segment as shown in the figure above. Erase the <> and its contents on the right hand side of the equality sign, right-click the Glove segment in the tree, and insert the
object name:

AnyFolder Joints = {
AnySphericalJoint rhHandle = {
AnyRefFrame &Glove = Main.Model.HumanModel.Right.ShoulderArm.Seg.Glove;
AnyRefFrame &Handle = <Insert object reference (or full object definition)>;
};
};

Similarly, locate the Handle node in the Wheel segment in the EnvironmentModel part of the tree and insert the name as the second reference frame:

AnyFolder Joints = {
AnySphericalJoint rhHandle = {
AnyRefFrame &Glove = Main.Model.HumanModel.Right.ShoulderArm.Seg.Glove;
AnyRefFrame &Handle = Main.Model.EnvironmentModel.Wheel.rHandle;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 172 of 229

};
};

It is advisable when modifying models to make changes in small steps and verify that the model is working for each step. That way you can avoid agonies over mistakes
that were made a long way upstream in the process. So, before we make the second connection between the left hand and the handle let us remove the now redundant
constraints on the right arm and verify that it can move. We resolved in the introduction to this lesson to remove the joint drivers for elbow flexion, shoulder rotation, and
shoulder flexion. Further down in the JointsAndDrivers file you can see that there is an include file with the drivers for each limb:

#if TRUNK == 1
#include "TrunkDrivers.any"
#else
#endif

#if RIGHT_ARM == 1
#include "RightArmDrivers.any"
#else
#endif

#if LEFT_ARM == 1
#include "LeftArmDrivers.any"
#else
#endif

#if RIGHT_LEG == 1
#include "RightLegDrivers.any"
#else
#endif

#if LEFT_LEG == 1
#include "LeftLegDrivers.any"
#else
#endif

Double click on "RightArmDrivers.any" to open the file, you should see the following:

// ************************************
// Drivers for the right arm
// ************************************

//Sterno clavicular joint driver


AnyKinEqSimpleDriver SCDriverRight ={
AnyKinMeasureOrg &ref1 =...HumanModel.Interface.Right.SternoClavicularJointProtraction;
AnyKinMeasureOrg &ref2 =...HumanModel.Interface.Right.SternoClavicularJointElevation;
AnyKinMeasureOrg &ref3 =...HumanModel.Interface.Right.SternoClavicularJointAxialRotation;
DriverPos = pi/180*{
.JntPos.Right.SternoClavicularJointProtraction,
.JntPos.Right.SternoClavicularJointElevation,
.JntPos.Right.SternoClavicularJointAxialRotation
};
DriverVel = {0.0,0.0,0};
Reaction.Type={Off,Off,Off};
};

//Glenohumeral joint
AnyKinEqSimpleDriver GHDriverRight={
AnyKinMeasureOrg &ref1 =...HumanModel.Interface.Right.GlenohumeralAbduction;
AnyKinMeasureOrg &ref2 =...HumanModel.Interface.Right.GlenohumeralFlexion;
AnyKinMeasureOrg &ref3 =...HumanModel.Interface.Right.GlenohumeralExternalRotation;
DriverPos=pi/180*{
.JntPos.Right.GlenohumeralAbduction, //GH joint
.JntPos.Right.GlenohumeralFlexion, //GH joint
.JntPos.Right.GlenohumeralExternalRotation //GH joint
};
DriverVel = pi/180*{
.JntVel.Right.GlenohumeralAbduction, //GH joint
.JntVel.Right.GlenohumeralFlexion, //GH joint
.JntVel.Right.GlenohumeralExternalRotation //GH joint
};
Reaction.Type={Off,Off,Off};
};

//Elbow flexion driver


AnyKinEqSimpleDriver ElbowFEDriverRight={
AnyKinMeasureOrg &Elbow =...HumanModel.Interface.Right.ElbowFlexion;
DriverPos=pi/180*{.JntPos.Right.ElbowFlexion};
DriverVel = pi/180*{.JntVel.Right.ElbowFlexion};
Reaction.Type={Off};
};

The elbow flexion driver is easy to remove simply by commenting it out. The glenohumeral driver has three separate degrees of freedom of which we can remove the
flexion and the joint rotation. When we do so, we must remember to also remove their entries in the DriversPos, DriverVel and Reaction.Type specifications:

//Glenohumeral joint
AnyKinEqSimpleDriver GHDriverRight={

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 173 of 229

AnyKinMeasureOrg &ref1 =...HumanModel.Interface.Right.GlenohumeralAbduction;


// AnyKinMeasureOrg &ref2 =...HumanModel.Interface.Right.GlenohumeralFlexion;
// AnyKinMeasureOrg &ref3 =...HumanModel.Interface.Right.GlenohumeralExternalRotation;
// DriverPos=pi/180*{
// .JntPos.Right.GlenohumeralAbduction, //GH joint
// .JntPos.Right.GlenohumeralFlexion, //GH joint
// .JntPos.Right.GlenohumeralExternalRotation //GH joint
// };
// DriverVel = pi/180*{
// .JntVel.Right.GlenohumeralAbduction, //GH joint
// .JntVel.Right.GlenohumeralFlexion, //GH joint
// .JntVel.Right.GlenohumeralExternalRotation //GH joint
// };
// Reaction.Type={Off,Off,Off};
DriverVel={0};
Reaction.Type={Off};
};
//Elbow flexion driver
// AnyKinEqSimpleDriver ElbowFEDriverRight={
// AnyKinMeasureOrg &Elbow =...HumanModel.Interface.Right.ElbowFlexion;
// DriverPos=pi/180*{.JntPos.Right.ElbowFlexion};
// DriverVel = pi/180*{.JntVel.Right.ElbowFlexion};
// Reaction.Type={Off};
// };

Try reloading the model and run the SetInitialConditions operation. The operation may fail, or you may get a chocking result like this:

How did that happen? Well, from a mechanical point-of-view, this solution is fully as good as the more anatomically compatible solution with the elbow bending the other
way. Postures like this and failure to resolve the initial position can happen because the problem is nonlinear. This means that the solution (or lack thereof) depends on the
starting position. So we must start the solution from a point that is closer to the result we want to get. This can be accomplished by imposing initial orientations on the
segments. In hard-core AnyScript development this is done by means of the two segment properties r0 and Axes0. However, the standing model on which this application
is built conveniently controls the initial posture through the mannequin.any file. So we can make the necessary changes there:

AnyFolder Right = {
//Arm
AnyVar SternoClavicularJointProtraction=-23; //This value is not used for initial position
AnyVar SternoClavicularJointElevation=11.5; //This value is not used for initial position
AnyVar SternoClavicularJointAxialRotation=-20; //This value is not used for initial position

AnyVar GlenohumeralFlexion = 50;


AnyVar GlenohumeralAbduction = 0;
AnyVar GlenohumeralInternalRotation = 0;

AnyVar ElbowFlexion = 40;

which causes the model to load with the arms closer to the desired posture. Notice that the mannequin file is set up to impose the same angles on the right and left hand
sides. You can now run the KinematicAnalysis operation and see the model turning the wheel 180 degrees and the right arm following along. With that working, we can

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 174 of 229

proceed to do exactly the same for the left arm. The first step is to add a joint, which we can copy from the one we just did for the right hand:

AnyFolder Joints = {
AnySphericalJoint rhHandle = {
AnyRefFrame &Glove = Main.Model.HumanModel.Right.ShoulderArm.Seg.Glove;
AnyRefFrame &Handle = Main.Model.EnvironmentModel.Wheel.rHandle;
};

AnySphericalJoint lhHandle = {
AnyRefFrame &Glove = Main.Model.HumanModel.Left.ShoulderArm.Seg.Glove;
AnyRefFrame &Handle = Main.Model.EnvironmentModel.Wheel.lHandle;
};
};

Notice the changes of 'Right' to 'Left' in the copy. The second step is to remove the redundant drivers on the left arm exactly as we did for the right arm. Open the file
"LeftArmDrivers.any":

//Glenohumeral joint driver


AnyKinEqSimpleDriver GHDriverLeft={
AnyKinMeasureOrg &ref1 =...HumanModel.Interface.Left.GlenohumeralAbduction;
// AnyKinMeasureOrg &ref2 =...HumanModel.Interface.Left.GlenohumeralFlexion;
// AnyKinMeasureOrg &ref3 =...HumanModel.Interface.Left.GlenohumeralExternalRotation;
// DriverPos=pi/180*{
// .JntPos.Left.GlenohumeralAbduction, //GH joint
// .JntPos.Left.GlenohumeralFlexion, //GH joint
// .JntPos.Left.GlenohumeralExternalRotation //GH joint
// };
// DriverVel = pi/180*{
// .JntVel.Left.GlenohumeralAbduction, //GH joint
// .JntVel.Left.GlenohumeralFlexion, //GH joint
// .JntVel.Left.GlenohumeralExternalRotation //GH joint
// };
// Reaction.Type={Off,Off,Off};
DriverVel={0};
Reaction.Type={Off};
};

//Elbow flexion driver


// AnyKinEqSimpleDriver ElbowFEDriverLeft={
// AnyKinMeasureOrg &Elbow =...HumanModel.Interface.Left.ElbowFlexion;
// DriverPos=pi/180*{.JntPos.Left.ElbowFlexion};
// DriverVel = pi/180*{.JntVel.Left.ElbowFlexion};
// Reaction.Type={Off};
// };

The left arm must also be positioned close to the posture is it going to take. Please make the following changes in the mannequin.any file:

AnyFolder Left = {
//all values are set to be equal to the right side values
//feel free to change this!

//Arm
AnyVar SternoClavicularProtraction=.Right.SternoClavicularProtraction;
AnyVar SternoClavicularElevation=.Right.SternoClavicularElevation;
AnyVar SternoClavicularAxialRotation=.Right.SternoClavicularAxialRotation;

AnyVar GlenohumeralFlexion = 0;
AnyVar GlenohumeralAbduction =.Right.GlenohumeralAbduction ;
AnyVar GlenohumeralExternalRotation =.Right.GlenohumeralExternalRotation ;

AnyVar ElbowFlexion = 100;

Now you should be able to run the kinematic analysis with both arms moving with the wheel. If you want to see an entire cycle, simply change tEnd in the study section in
the main file from 1 to 2 seconds:

AnyBodyStudy Study = {
AnyFolder &Model = .Model;
tEnd = 2.0;
Gravity = {0.0, -9.81, 0.0};
nStep = 10;
}; // End of study

Notice that you can furthermore control the pronation of the forearms by the setting in the mannequin file if you so desire. Notice also that, since we have retained the
driver on the shoulder abduction, the lateral movement of the elbows may be unnatural. A natural movement can be imposed by information about the lateral elbow
position from, for instance, a motion capture experiment.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 175 of 229

Here is a helping hand if you did not succeed making the model in this lesson work: HandPump.3.zip .

With the kinematics in place, let us proceed to the computation of forces: Lesson 4: Kinetics .

Lesson 4: Kinetics
Having persuaded the model to move correctly we shall proceed to the task of imposing external forces and computing muscle and joint forces in the system.

The AnyBody Modeling System allows you to distinguish clearly between kinematics and kinetics, which is a huge advantage when creating models like this one. In the
real world, the muscles would be pulling on the bones, which causes the arms to exert forces on the handles, which subsequently creates the movement of the wheel. The
distinction between kinematics and kinetics in AnyBody allows you to let the wheel rotation impose the kinematics of the entire system, i.e. reversely of how it happens in
the real world, while the forces flow the correct way from the muscles to the handles.

To make this happen, we must make a couple of additions to the model. Both concern the definition of the wheel in the Environment.any file. When you open the file you
can find the definition of the driver that makes the wheel revolve. To this driver we must add the following setting:

AnyKinEqSimpleDriver WheelTurn = {
AnyRevoluteJoint &Hub = .WheelHub;
DriverVel = {-pi};
Reaction.Type = {Off}; // No motor in the driver
};

This setting ensures that the driver does not provide any torque to the wheel, and it is separation of kinematics and kinetics in a nutshell: The driver provides the wheel
rotation, which further down the kinematic chain causes the arms to move too, but it does not provide any sort of torque, so other elements in the system must do the work.
We have to set everything up so that those "other elements" are the muscles. Right now the muscles would not have a very difficult time providing the work because the
wheel still has no resistance to work against. This we can provide by means of an applied torque. We shall presume that the arms are driving the wheel against a constant
torque, which we can apply as an AnyForce to the hub:

AnyKinEqSimpleDriver WheelTurn = {
AnyRevoluteJoint &Hub = .WheelHub;
DriverVel = {-pi};
Reaction.Type = {Off}; // No motor in the driver
};

AnyForce WheelTorque = {
AnyRevoluteJoint &Hub = .WheelHub;
F = {30};
};

AnyForce is a generic force object that imposes an external load on whatever kinematic measure you apply it to. If the measure is linear in nature, then the load is a force.
If the measure is rotational as in the case of the revolute joint in the wheel, then the load becomes a torque. In the present case we are applying 30 torque units of load to the
wheel, and because the wheel driver has no motor, this torque must be balanced by the muscles in the system.

There are just a couple of things to do to ice the cake. The first thing issue is that the original standing model has its forward/backward posture driven to maintain balance.
This makes sense for a freely standing model, but probably not for a model holding on to a wheel. A more reasonable way to do it would be to control the distance between
the thorax and the wheel hub. Let us initially remove the Center of Mass driver that is responsible for the balancing condition. This takes place in the JointAndDrivers.any
file:

//Constrain the collective CoM to be right above the GlobalRef


// AnyKinEqSimpleDriver CoMDriver = {
// AnyKinCoM CoM = {
// AnyFolder &Body = Main.Model.HumanModel;
// };
// MeasureOrganizer = {0,2}; // Only the x and z directions
// DriverPos = {0,0};
// DriverVel = {0,0};
// Reaction.Type = {Off,Off};
// };

This driver we replace by another driver that controls the two horizontal positions of the thorax with respect to the wheel hub. As you can see, this is pretty much a copy of
the CoM driver that we just removed with the exception of the changed measure inside the driver. You can use the tree view to insert the long references to the wheel hub
node and the thorax segment.

//Constrain thorax with respect to the wheel hub


AnyKinEqSimpleDriver WheelThorax = {
AnyKinLinear Lin = {
AnyRefFrame &Hub = Main.Model.EnvironmentModel.GlobalRef.Hub;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 176 of 229

AnyRefFrame &Thorax = Main.Model.HumanModel.Trunk.SegmentsThorax.ThoraxSeg;


};
MeasureOrganizer = {0,2}; // Only the x and z directions
DriverPos = {-0.4, 0};
DriverVel = {0,0};
Reaction.Type = {Off,Off};
};

The DriverPos specification in this driver allows you to control how far the body should be from the wheel. Obvously the body cannot be so close that it touches the wheel
and it cannot be so far away that it cannot reach the handles. The value of -0.4 will make the body roughly vertical. If you load the model and run the kinematic analysis,
you will see the result. Try experimenting a bit with the distance if you like.

Closer investigation will reveal that the forearm pronation is a bit unrealistic for a hand wheel.

The simple way to remedy this situation is to change the forearm pronation in the mannequin.any file:

AnyFolder Right = {
//Arm
AnyVar SternoClavicularProtraction=-23; //This value is not used for initial position
AnyVar SternoClavicularElevation=11.5; //This value is not used for initial position
AnyVar SternoClavicularAxialRotation=-20; //This value is not used for initial position

AnyVar GlenohumeralFlexion = 50;


AnyVar GlenohumeralAbduction = 0;
AnyVar GlenohumeralExternalRotation = 0;

AnyVar ElbowFlexion = 40.0;


AnyVar ElbowPronation = 20.0;

Finally, to not have too large time steps, let us define a slightly higher resolution in the AnyBodyStudy in the main file:

AnyBodyStudy Study = {
AnyFolder &Model = .Model;
tEnd = 2.0;
Gravity = {0.001, -9.81, 0.001};
nStep = 20;
}; // End of study

With this completed, we are ready to attempt an inverse dynamic analysis. For this we need muscles in the model, so we switch the muscles back in by changing the
BodyPartsSetup file:

// Trunk: 1 included, 0 not included


// *********************************
#define TRUNK 1
// This is just the bones,
// Choose one of the following options to add muscles
#define TRUNK_SIMPLE_MUSCLES 1

// RightArm: 1 included, 0 not included


// ************************************
#define RIGHT_ARM 1
// This is just the bones,
// Choose one of the following options to add muscles
#define RIGHT_ARM_SIMPLE_MUSCLE 1
#define RIGHT_ARM_SIMPLE_MUSCLE_ONLY_ON_NECK 0
#define RIGHT_ARM_MUS_3E 0

// LeftArm: 1 included, 0 not included


// ***********************************
#define LEFT_ARM 1
// This is just the bones,
// Choose one of the following options to add muscles
#define LEFT_ARM_SIMPLE_MUSCLES 1
#define LEFT_ARM_SIMPLE_MUSCLES_ONLY_ON_NECK 0
#define LEFT_ARM_MUS_3E 0

// RightLeg: 1 included, 0 not included


// ************************************
#define RIGHT_LEG 1
// This is just the bones,
// Choose one of the following options to add muscles
#define RIGHT_LEG_SIMPLE_MUSCLES 1

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 177 of 229

#define RIGHT_LEG_MUS_3E 0

// LeftLeg: 1 included, 0 not included


// ***********************************
#define LEFT_LEG 1
// This is just the bones,
// Choose one of the following options to add muscles
#define LEFT_LEG_SIMPLE_MUSCLES 1
#define LEFT_LEG_MUS_3E 0

This type of loading of the model causes a torsional moment along the length axis of the body because one hand is pushing on the pedal while the other is pulling. This
turns out to make it difficult for the fully extended knees as they are in the current model to carry the load, so it is advisable to flex the knees slightly by the knee flexion
setting in the mannequin file:

AnyVar KneeFlexion = 5.0;

With these changes performed, please click the InverseDynamicAnalysis operation in the study tree and hit the run button. You should see the model turning the wheel
against the imposed crank torque. Please beware that with more than 500 muscles in the model each step takes a considerable time.

That is pretty much all there is to it. You should now be able to load the model and run the InverseDynamicAnalysis to investigate the muscle actions, joint forces and so
on.

Here's a set of files that work in case the model is giving you trouble: HandPump.4.zip .

Modifications like these from an existing application to a new one probably accounts for 90% of the model development of AnyBody users. However, in some cases it is
not possible to find a good existing application, and it can be advantageous to build your own model from the body parts in the repository.

The next lessons, starting with Lesson 5 , deal with such a case.

Lesson 5: Starting with a new model


In the previous lessons we have been constructing our model by modification of an existing application, namely the Standing Model. In some cases it may be difficult to
find an existing model that is sufficiently similar to what you want to obtain. In such a case it can be reasonable to begin the modeling project from a new model rather than
an existing model. This is what we shall explore in the forthcoming lessons. We shall design a model of a single leg stepping on a pedal. Such a model is much more
numerically efficient than the model of the previous lessons, and therefore it makes no sense to begin the project from the standing model as we did before.

Let us first review the structure of the repository in slightly more detail. One of the objectives of its structure is to enable a clear division between the body parts and the
applications we hook them up to. This comes through in the data structure of the model we are going to construct. Here is a brief overview of the principles behind that
structure.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 178 of 229

The model is primarily divided into three folders (a folder is a container of different objects much like a directory can contain files) as shown above. In fact, the structure
contains a few more parts that we will get to later, but the elements shown above are the more important.

In the middle you see the "HumanModel". This is where we keep the body parts that we are importing from the Body part of the repository. This folder contains objects
such as segments (bones), joints, muscles, and ligaments. We also keep information about the scaling of the model in this folder.

It is just as important to notice what this folder does not contain: movement drivers, forces, and joints between the model and the environment. The external hardware parts
of the models such as chairs, bicycles, tools, or, in the present case, a pedal are stored in the Environment.

To link the body model together with the environment we create a "ModelEnvironmentConnection" folder typically containing the joint between the objects of the two
former folders.

The "Mannequin" part of the model is used for specification of postures, and we shall return to this issue in more detail later.

Without further ado, let us start building the foot pedal model. The toolbar button "New Main" will generate an empty model that looks much like this (we have changed
the name of the MyModel folder to MyPedal):

// This model demonstrates the construction of a foot pedal example


Main = {
// The actual body model goes in this folder
AnyFolder MyPedal = {
// Global Reference Frame
AnyFixedRefFrame GlobalRef = {
}; // Global reference frame
}; // MyPedal
// The study: Operations to be performed on the model
AnyBodyStudy MyStudy = {
AnyFolder &Model = .MyPedal;
Gravity = {0.0, -9.81, 0.0};
};
}; // Main

The comments have been adapted to reflect the fact that we are going to construct a pedal example. Please press the save button (or Ctrl-S) and save the model in a new
directory under Application, for instance using the file name Pedal.Main.any. Notice that the use of the "Main" suffix is a good way to indicate that this is the starting point
of the pedal application.

The model can be compiled, but it does not do much, and in any case we shall restructure it right away. As indicated above, we wish to separate the parts that deal with the
environment into a dedicated file. Press the "New Include" button.

This gives you an empty window. Now fill the following into the new include file:

AnyFolder EnvironmentModel = {
};

This folder is for keeping stuff that forms the environment. In this case it is the global reference frame, i.e. ground, and the pedal that the foot is going to step on. In fact,
let's move the global reference frame to this folder right away. Simply cut the GlobalRef definition from the Pedal.Main.any file and insert it into the include file (notice
that new AnyScript code is written in red while existing code has the usual syntax highlighting):

AnyFolder EnvironmentModel = {
// Global Reference Frame
AnyFixedRefFrame GlobalRef = {
}; // Global reference frame

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 179 of 229

};

It is time to save the new include file. Click the "Save" button or Ctrl-S and save it under the name of "Environment.any" in the same directory as the Main file.

The next step is to add an include statement in the Main file that incorporates the environment into the model:

Main = {
// The actual body model goes into this folder
AnyFolder MyPedal = {
#include "Environment.any"
}; // MyPedal

We now have the framework for adding the pedal to the model. We are presuming a pedal hinged in one end and the foot pushing in the other. We define the segment and
the hinge in the Environment.any file:

AnyFolder EnvironmentModel = {
// Global Reference Frame
AnyFixedRefFrame GlobalRef = {
}; // Global reference frame
AnySeg Pedal = {
Mass = 2;
Jii = {0.05, 0.001, 0.05};
AnyRefNode Hinge = {
sRel = {0, -0.15, 0};
};
AnyRefNode FootNode = {
sRel = {0, 0.15, 0};
};
AnyDrawSeg drw = {};
};
AnyRevoluteJoint HingeJoint = {
Axis = z;
AnyFixedRefFrame &Ground = .GlobalRef;
AnyRefNode &Pedal = .Pedal.Hinge;
};
};

If you load the model and open a Model View, then you will see the new segment:

It is hinged to the origin of the global reference frame, but there is not much else to see. In the next lesson we shall look at how we can import a leg model from the
repository to step on the pedal.

Next up is Lesson 6: Importing a Leg Model .

Lesson 6: Importing a Leg Model


Having defined the environment, the next step is to introduce a leg into the model. We are going to pick one from the repository. The body model is divided into individual
body parts: legs, arms and trunk. In top of that each body part presents several versions: with or without muscles, simple or advanced muscle model, etc.

In earlier versions it was not easy to pick individual body parts to construct your model because the necessary interfaces had to be provided manually, so a collection of
predefined body part collections ready to was located in a folder named BodyModels. However this simple solution has limitations. A new set of files has to be created for
each possible body combination, so this predefined collection contains the fifteen most used body models. These are enough in the majority of the cases, but it is not
possible to list all the variations that could be needed for more advanced modeling, this would lead to thousands of predefined bodies to choose from, which is certainly not
convenient.

In the AnyBody Managed Model Repository it is now possible to easily create custom body models by simply picking out individual parts. All interface files which are
needed will then be included automatically. The selection of the body parts is done using a file called BodyPartsSetup.any. This file is typically found in the applications
(as it is application dependent) but a template is available in the Body section of the repository. For this tutorial you may use this model . Please locate the directory

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 180 of 229

“AMMRV1BlockTutorial\Body\AAUHuman\BodyModels\Include” and the BodyPartsSetup file, copy and paste it inside the PedalModel directory. We should also
include the file in the AnyScript code.

Main = {
// The actual body model goes in this folder
AnyFolder HumanModel={
// Select the body model:
// ----------------------
// This file contains a list of all body parts, select them to create
// the body model wanted.
#include "BodyPartsSetup.any"
};

AnyFolder MyPedal = {
#include "Environment.any"
}; // MyPedal

// The study: Operations to be performed on the model


AnyBodyStudy MyStudy = {
AnyFolder &Model = .MyPedal;
Gravity = {0.0, -9.81, 0.0};
};
}; // Main

Notice that we have created a new folder named 'HumanModel' and inserted the include statement into it. The separate folder for the human model allows us to add a few
necessary additional items. As we said the file BodyPartsSetup.any allows you to pick the body parts. But it is actually just a list, and it will not assemble the body. We
need a second file that will read the list in BodyPartsSetup and create the body model according to it. Please insert the following line.

AnyFolder HumanModel={
// Select the body mode
// ----------------------
// This file contains a list of all body parts, select them to create
// the body model wanted.
#include "BodyPartsSetup.any"

// This file creates the body model from the selected list.
#include "..\..\..\Body\AAUHuman\BodyModels\GenericBodyModel\BodyModel.any"
};

This last file is in general to be left untouched, it creates the body model automatically by using a number of IF functions. The BodyPartsSetup file is more interesting;
double click on the line to open the file. You should see the following.

// Trunk: 1 included, 0 not included


// *********************************
#define TRUNK 1
// This is just the bones,
// Choose one of the following options to add muscles
#define TRUNK_SIMPLE_MUSCLES 0

// Trunk with neck: 1 included, 0 not included


// *********************************
#define TRUNK_NECK 0
// This is just the bones,
// Choose one of the following options to add muscles
#define TRUNK_NECK_SIMPLE_MUSCLES 0
#define TRUNK_NECK_SIMPLE_MUSCLES_ONLY_ON_NECK 0

// RightArm: 1 included, 0 not included


// ************************************
#define RIGHT_ARM 1
// This is just the bones,
// Choose one of the following options to add muscles
#define RIGHT_ARM_SIMPLE_MUSCLE 0
#define RIGHT_ARM_SIMPLE_MUSCLE_ONLY_ON_NECK 0
#define RIGHT_ARM_MUS_3E 0

// LeftArm: 1 included, 0 not included


// ***********************************
#define LEFT_ARM 1
// This is just the bones,
// Choose one of the following options to add muscles
#define LEFT_ARM_SIMPLE_MUSCLES 0
#define LEFT_ARM_SIMPLE_MUSCLES_ONLY_ON_NECK 0
#define LEFT_ARM_MUS_3E 0

// RightLeg: 1 included, 0 not included


// ************************************
#define RIGHT_LEG 1
// This is just the bones,
// Choose one of the following options to add muscles

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 181 of 229

#define RIGHT_LEG_SIMPLE_MUSCLES 0
#define RIGHT_LEG_MUS_3E 0

// LeftLeg: 1 included, 0 not included


// ***********************************
#define LEFT_LEG 1
// This is just the bones,
// Choose one of the following options to add muscles
#define LEFT_LEG_SIMPLE_MUSCLES 0
#define LEFT_LEG_MUS_3E 0

// RightLegTD: 1 included, 0 not included


// ************************************
#define RIGHT_LEG_TD 0
// This is just the bones,
// Choose one of the following options to add muscles
#define RIGHT_LEG_TD_SIMPLE_MUSCLES 0
#define RIGHT_LEG_TD_MUS_3E 0

// LeftLegTD: 1 included, 0 not included


// ***********************************
#define LEFT_LEG_TD 0
// This is just the bones,
// Choose one of the following options to add muscles
#define LEFT_LEG_TD_SIMPLE_MUSCLES 0
#define LEFT_LEG_TD_MUS_3E 0

As you see the file lists all the individual body parts, each one with its different available versions. Let’s have a closer look at the right leg.

The first define statement is a global switch for the leg. When set to 1 the leg is included and when set to 0 the leg is not included. Please notice that RIGHT_LEG includes
the leg without muscle. You want the muscles to be included you have to set one of the muscle models to 1. So typically for a body part you can choose the three following
version:

1. With no muscles: a version where all the anatomical muscles have been replaced by simple joint torque muscles. This is useful for development, because the model
loads and runs much faster in this version, and for traditional joint-torque-type inverse dynamics.
2. With simple muscles: the basic version including simple muscle models, i.e. muscles that have constant strength regardless of length and contraction velocity.
3. With three-elements muscles, also called Mus3E: the version with Hill-type, three-element muscles that take the complexities of contraction dynamics, tendon
elasticity, and many other physiological properties into account.

Of course you cannot switch on both muscle models at the same time, that will generate an error message. You should also notice that the two last define statement are
really for the muscles only, so if RIGHT_LEG is set to 0 then nothing will be included at all, no matter if you select a muscle model or not.

So now that we learned to use the body setup we should practice and create the body model we are interested in, the right leg. We will also include the trunk because the
psoas muscles of the trunk model have their insertion point on the femur. The template of the BodyPartsSetup file we just copied is defining a full body model without
muscles. Let’s modify it to create our right leg and trunk model, without muscles also for the moment as we said it is useful for the development phase.

// Trunk: 1 included, 0 not included


// *********************************
#define TRUNK 1
// This is just the bones,
// Choose one of the following options to add muscles
#define TRUNK_SIMPLE_MUSCLES 0

...

// RightArm: 1 included, 0 not included


// ************************************
#define RIGHT_ARM 0
// This is just the bones,
// Choose one of the following options to add muscles
#define RIGHT_ARM_SIMPLE_MUSCLE 0
#define RIGHT_ARM_SIMPLE_MUSCLE_ONLY_ON_NECK 0
#define RIGHT_ARM_MUS_3E 0

// LeftArm: 1 included, 0 not included


// ***********************************
#define LEFT_ARM 0
// This is just the bones,
// Choose one of the following options to add muscles
#define LEFT_ARM_SIMPLE_MUSCLES 0
#define LEFT_ARM_SIMPLE_MUSCLES_ONLY_ON_NECK 0
#define LEFT_ARM_MUS_3E 0

// RightLeg: 1 included, 0 not included


// ************************************

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 182 of 229

#define RIGHT_LEG 1
// This is just the bones,
// Choose one of the following options to add muscles
#define RIGHT_LEG_SIMPLE_MUSCLES 0
#define RIGHT_LEG_MUS_3E 0

// LeftLeg: 1 included, 0 not included


// ***********************************
#define LEFT_LEG 0
// This is just the bones,
// Choose one of the following options to add muscles
#define LEFT_LEG_SIMPLE_MUSCLES 0
#define LEFT_LEG_MUS_3E 0

We previously mentioned that the body model was included into the folder named 'HumanModel' to allows us to add a few necessary additional items. You will see the
necessity of this if you try to load the model by pressing F7. This should produce the following error message:

ERROR(SCR.PRS9) : R..l/Body/A..n/T..k/PelvisSeg.any : 'ScaleFunction' : Unresolved object

It appears that an object named ' ScaleFunction ' is missing from the model. All the body models in the repository are set up to expect some sort of scaling to be defined by
the user. The repository comes with a number of different scaling laws, and it is possible for the advanced user to define new scaling laws. This, however, is a worthy
subject of a separate tutorial, so here we shall just chose the simplest solution, which is to use the standard scaling. This really means that we do not scale at all but simply
use the body models in the size they were originally defined, i.e. roughly like a 50th percentile European male:

AnyFolder HumanModel={
// Select the body model:
// ----------------------
// This file contains a list of all body parts, select them to create
// the body model wanted.
#include "BodyPartsSetup.any"

// This file creates the body model from the selected list.
#include "..\..\..\Body\AAUHuman\BodyModels\GenericBodyModel\BodyModel.any"

#include "..\..\..\Body\AAUHuman\Scaling\ScalingStandard.any"
};

Now we are at it, we also need to set the basic strength of muscles in the different body parts:

AnyFolder HumanModel={
...
#include "..\..\..\Body\AAUHuman\Scaling\ScalingStandard.any"
AnyFolder StrengthParameters={
AnyVar SpecificMuscleTensionSpine= 90; //N/cm^2
AnyVar StrengthIndexLeg= 1;
AnyVar SpecificMuscleTensionShoulderArm= 90; //N/cm^2
};
#include "..\..\..\Body\AAUHuman\Scaling\ScalingStandard.any"
};

The strengths of the body parts scale differently. For the spine and shoulder complex the model needs a specific stress of the muscle tissue, while the legs need a strength
index. However, in both cases a change of the numbers will scale the strength of the body part accordingly. This gives easy opportunity to, for instance, reduce the strength
of the body when modeling an elderly individual.

When you load the model again you will get a new error message:

ERROR(SCR.PRS9) : R..l/Body/A..n/B..s/I..e/SettingsTrunk.any : 'Colors' : Unresolved object

Colors is the local name of a folder inside the body models. It expects a folder defined in the model containing definitions of colors of the various objects in the model. All
the applications in the repository use the same color setup, which is responsible for the graphical similarity between the different applications, i.e. bones, muscles and such
with the same colors. To use the same settings here, click the New Include icon,

and fill the following into the new file:

AnyFolder DrawSettings ={

//This is the color definitions of the nodes and segments


AnyFolder Colors = {
AnyVec3 AnyBodyRed = {149/256,51/256,55/256}; //AnyBody standard red
AnyVec3 AnyBodyGreen = {47/256,131/256,80/256}; //AnyBody standard green
AnyVec3 AnyBodyBlue = {82/256,85/256,111/256}; //AnyBody standard blue
AnyVec3 AnyBodyYellow= {235/256,197/256,17/256}; //AnyBody standard yellow
AnyVec3 AnyBodyPaleYellow = {248/256,204/256,115/256}; //AnyBody standard pale yellow

AnyVec3 Nodes = AnyBodyPaleYellow;


AnyVec3 Segments = AnyBodyPaleYellow;
};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 183 of 229

AnyFolder Muscle ={
AnyVec3 RGB = .Colors.AnyBodyRed;
AnySwitch Visible = On;
AnyVar Bulging = 1.0;
AnyVar ColorScale =1.0;
AnyVec3 RGBColorScale = {0.957031, 0.785156, 0.785156};
AnyVar MaxStress = 100000.000000; //N/m^2 //This number is for graphics only!
AnyVar Opacity =1.0;

};

AnyFolder BonesOpacity ={

AnyVar GlobalCoef = 1;

AnyVar Skull = 1*GlobalCoef;


AnyVar Thorax = 1*GlobalCoef;
AnyVar Pelvis = 1*GlobalCoef;
AnyVar Sacrum = 1*GlobalCoef;
AnyVar L5 = 1*GlobalCoef;
AnyVar L4 = 1*GlobalCoef;
AnyVar L3 = 1*GlobalCoef;
AnyVar L2 = 1*GlobalCoef;
AnyVar L1 = 1*GlobalCoef;

AnyVar RightFoot = 1*GlobalCoef;


AnyVar RightShank = 1*GlobalCoef;
AnyVar RightThigh = 1*GlobalCoef;

AnyVar LeftFoot = 1*GlobalCoef;


AnyVar LeftShank = 1*GlobalCoef;
AnyVar LeftThigh = 1*GlobalCoef;

AnyVar RightClavicula = 1*GlobalCoef;


AnyVar RightScapula = 1*GlobalCoef;
AnyVar RightHumerus = 1*GlobalCoef;
AnyVar RightUlna = 1*GlobalCoef;
AnyVar RightRadius = 1*GlobalCoef;
AnyVar RightHand = 1*GlobalCoef;

AnyVar LeftClavicula = 1*GlobalCoef;


AnyVar LeftScapula = 1*GlobalCoef;
AnyVar LeftHumerus = 1*GlobalCoef;
AnyVar LeftUlna = 1*GlobalCoef;
AnyVar LeftRadius = 1*GlobalCoef;
AnyVar LeftHand = 1*GlobalCoef;

// For leg TD only.


AnyVar RightTalus = 1*GlobalCoef;
AnyVar RightPatella = 1*GlobalCoef;

AnyVar LeftTalus = 1*GlobalCoef;


AnyVar LeftPatella = 1*GlobalCoef;

// For detailed cervical model only.


AnyVar C1 = 1*GlobalCoef;
AnyVar C2 = 1*GlobalCoef;
AnyVar C3 = 1*GlobalCoef;
AnyVar C4 = 1*GlobalCoef;
AnyVar C5 = 1*GlobalCoef;
AnyVar C6 = 1*GlobalCoef;
AnyVar C7 = 1*GlobalCoef;
};

AnyFolder SegmentAxes ={
AnyVec3 RGB ={0,0,1};
AnyVec3 ScaleXYZ ={0.0001,0.00001,0.00001};
};
AnyFolder BML ={
AnyVec3 ScaleXYZ ={0.0006,0.0006,0.0006};
AnyVec3 RGB = .Colors.AnyBodyBlue;
};
AnyFolder JointAxesProximal = {
AnyVec3 RGB = .Colors.AnyBodyRed;
AnyVec3 ScaleXYZ = {0.015,0.015,0.015};
};
AnyFolder JointAxesDistal = {
AnyVec3 RGB = .Colors.AnyBodyGreen;
AnyVec3 ScaleXYZ = {0.01,0.01,0.01};
};

AnyFolder SegmentNodes ={
AnyVec3 ScaleXYZ ={0.0005,0.0005,0.0005};
AnyVec3 RGB = .Colors.AnyBodyRed;
};
AnyFolder WrapGeometry ={
AnyVec3 RGB ={1,1,1};
};

AnyFolder DrawSettingsSupport={
AnyFolder Lin={
AnyVar ScaleFactor=0.004;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 184 of 229

AnyVec3 RGB = {0,0,1};


AnyVar Thickness = 0.004;
AnyVar HeadThickness = 2*Thickness;
AnyVar HeadLength = 3*Thickness;
};
AnyFolder Rot={
AnyVar ScaleFactor=0.08;
AnyVec3 RGB = {1,0,0};
AnyVar Thickness = 0.075;
AnyVar HeadThickness = 2*Thickness;
AnyVar HeadLength = 5*Thickness;
};
};

AnyFolder DrawSettingsJointReactions={
AnyFolder Lin={
AnyVar ScaleFactor=0.0005;
AnyVec3 RGB = {0,0,1};
AnyVar Thickness = 0.01;
AnyVar HeadThickness = 2*Thickness;
AnyVar HeadLength = 3*Thickness;
};
AnyFolder Rot={
AnyVar ScaleFactor=0.001;
AnyVec3 RGB = {1,0,0};
AnyVar Thickness = 0.01;
AnyVar HeadThickness = 2*Thickness;
AnyVar HeadLength = 5*Thickness;
};
};

AnyFolder Names={
AnyVec3 RGB={0,0,1};
AnyVec3 ScaleXYZ={0.01,0.01,0.01};
};

AnyFolder Marker={
AnyVec3 Color={0,0,1};
AnyVar Radius=0.005;

};
}; //DrawSettings

Then save the new file under the name "DrawSettings.any". The beauty of all this is that it allows you to very easily change many of the graphical settings of the entire
model just by changing a few numbers in this file. For instance, if you want to give all the bones in the model a new color, then simply edit the blend of red, green and blue
for the AnyBodyPaleYellow setting near the top of the file.

To use these settings, the following must be added to the Pedal.Main.any file:

Main = {

#include "DrawSettings.any"

// The actual body model goes in this folder


AnyFolder HumanModel = {

Try loading the model again. F7 should produce one last error message:

ERROR(SCR.PRS9) : R..l/Body/A..n/T..k/InitialPositionsPelvis.any : 'JointPos' : Unresolved object

The system needs to be given some initial positions for the segments. This is done by the Mannequin.any file. As it is quite a long file we will simply copy the one of the
standing model. Go into the StandingModel directory, copy the Mannequin file and paste it in the PedalModel directory. We also need to include the file in the code, for
structural reason it is included in the folder MyPedal and then referred to in the folder HumanModel

AnyFolder HumanModel={

AnyFolder &Mannequin=.MyPedal.Mannequin;
...
};

AnyFolder MyPedal = {
#include "Environment.any"

#include "Mannequin.any"

}; // MyPedal

As we are into structural adjustments, maybe you noticed that we have now two folders: HumanModel containing the human body and MyPedal containing the pedal and
the connection elements. However if you look in the AnyBodyStudy you will see that it only perform the study on the folder MyPedal. The HumanModel is not part of the
study yet. The easy solution is to simply make a reference to HumanModel inside MyPedal.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 185 of 229

AnyFolder MyPedal = {

AnyFolder &HumanModel=.HumanModel.BodyModel;

#include "Environment.any"

#include "Mannequin.any"

}; // MyPedal

Try loading the model again. F7 should produce the encouraging message:

Model Warning: Study 'Main.MyStudy' contains too few kinematic constraints to be kinematically determinate.
Evaluating model...
Loaded successfully.
Elapsed Time : 0.831000

The model view should show you the following picture:

The warning message about the model containing too few kinematic constraints means that it is not ready yet to perform any movement. We have not made any
specifications yet of how everything in the model is connected. This will be the topic of Lesson 7: Making Ends Meet .

Lesson 7: Making Ends Meet


So far we have accomplished to define an environment model with a simple pedal and a body model containing the trunk and the right leg. What the application is still
missing is specifications of how the different elements are connected and how the model moves. With kinematics it is usually a good idea to begin with an inventory of
degrees of freedom (DOFs) in the model.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 186 of 229

The pedal is simple: It is hinged to the global reference frame and therefore just has just one movement capability, namely a rotation about the hinge. The body model is
more complicated. It is disconnected from everything and is therefore floating around in space. Furthermore it has a number of internal degrees of freedom that must be
controlled: Three rotations in the trunk, three rotations in the hip, one rotation in the knee, and two rotations in the ankle. With the nine DOFs of the entire body model in
space and the single DOF of the pedal, this adds up to 16 DOFs. In other words, we need 16 constraints before the model is kinematically determinate.

This is what we plan to do:

1. The pelvis will be fixed completely at a point corresponding to the contact to a seat. This will do away with 6 DOFs leaving us with 10 more to specify.
2. The 3 rotations of the trunk will be specified by a driver to a constant position. This leaves us with 7 more constraints to specify.
3. The foot will be connected to the pedal by a spherical joint having 3 constraints. This leaves us with 4 more constraints to specify.
4. The ankle angle will be presumed fixed by two constraints. This leaves 2 DOFs to be constrained.
5. The lateral position of the knee will be specified by a driver. This leaves a single degree of freedom in the system.
6. Finally, we are going to drive the pedal angle. With the aforementioned constraints this will allow us to specify the posture of the entire system by this single driver.

1. Fixing the pelvis to the global reference frame

We previously joined the pedal to the origin of the global reference frame. This means that the 'seat' to which we shall fix the pelvis must be displaced a suitable distance
from the origin. In the Environment.any file, add the following to the definition of the GlobalReferenceFrame:

AnyFixedRefFrame GlobalRef = {
AnyRefNode Hpoint = {
sRel = {-0.7, 0.5, 0};
};
}; // Global reference frame

The name Hpoint is a term used in the seating industry to characterize the position of the pelvis in a seat. Here we shall simply attach the pelvis to this point by means of a
rigid connection.

All such specifications are traditionally put into a folder called ModelEnvironmentConnection, and for historical reasons it is placed in an include file called
JointsAndDrivers.any. Hit the 'New Include' button

on the toolbar. It brings up an empty window where we can define the objects we need.:

// This file contains the connections between the model


// and the environment along with the motion drivers
AnyFolder Joints = {
AnyStdJoint SeatPelvis = {
AnyRefNode &Seat = ;
AnySeg &Pelvis = ;
};

};

The local pointer variables &Seat and &Pelvis need something to point to. The best way of locating the necessary points is to use the object tree at the left hand side of the
editor window. Place your cursor in the editor window on the &Seat line just before the final semicolon. Then expand the three in the left hand side of the window through
MyPedal, EnvironmentModel, GlobalRef to find the Hpoint that we defined previously. Right-click Hpoint and choose 'Insert Object Name'. The full name of the Hpoint is
inserted at the position of the cursor.

We must repeat the procedure for the Pelvis. Place the cursor on the &Pelvis line just before the semicolon and subsequently expand the object tree through HumanModel,
BodyModel, Trunk, SegmentsLumbar. Inside the lumbar segments folder you will find the PelvisSeg. Right-click and insert the object name. You should now have the
following:

AnyFolder Joints = {
AnyStdJoint SeatPelvis = {
AnyRefNode &Seat = Main.MyPedal.EnvironmentModel.GlobalRef.Hpoint;
AnySeg &Pelvis = Main.HumanModel.BodyModel.Trunk.SegmentsLumbar.PelvisSeg;
};
};

Save the file under the name JointsAndDrivers.any. Then insert the necessary include statement into the main file:

AnyFolder MyPedal = {

AnyFolder &HumanModel=.HumanModel.BodyModel;

#include "Environment.any"

#include "Mannequin.any"

AnyFolder ModelEnvironmentConnection = {
#include "JointsAndDrivers.any"
};

}; // MyPedal

Hit F7 to reload the model. The model still loads in the same position as before. If you run the SetInitialConditions operation, the body model may move backward with the
pelvis to the point you have specified (You may have to click the model view to update the picture). This brings up the challenge of getting the model elements aligned
reasonably at load time. This is an important topic because the model will be unable to resolve the initial conditions when we add more constraints if all the segments are
loaded in a big mess on top of each other.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 187 of 229

As you might remember from the previous lesson the initial positions are controlled by the mannequin file. Open it up and make the following changes:

AnyFolder Mannequin = {

AnyFolder Posture = {
//This controls the position of the pelvis wrt. to the global reference frame
AnyVar PelvisPosX = -0.7;
AnyVar PelvisPosY = 0.5;
AnyVar PelvisPosZ = 0;

What we have done here is to specify the load-time position of the pelvis to the place where we have the seat. After reload you should be able to see in the model view that
the body model has moved to a new position. It is also a good idea to specify the initial joint angles so that the foot comes closer to the pedal. This can be done further
down in the Mannequin file:

AnyFolder Right = {
//Arm
AnyVar SternoClavicularProtraction=-23; //This value is not used for initial position
AnyVar SternoClavicularElevation=11.5; //This value is not used for initial position
AnyVar SternoClavicularAxialRotation=-20; //This value is not used for initial position

AnyVar GlenohumeralFlexion =-0;


AnyVar GlenohumeralAbduction = 10;
AnyVar GlenohumeralExternalRotation = 0;

AnyVar ElbowFlexion = 0.01;


AnyVar ElbowPronation = 10.0;

AnyVar WristFlexion =0;


AnyVar WristAbduction =0;

AnyVar HipFlexion = 110.0;


AnyVar HipAbduction = 5.0;
AnyVar HipExternalRotation = 0.0;

AnyVar KneeFlexion = 100.0;

On reload you will see that the body now loads in pretty much the desired position. Notice that this is only to bring the body close to where it will eventually be. It is not
necessary to align the model exactly with the pedal. The kinematic constraints will take care of this once they are properly defined.

2. Fix the trunk position

In this model the trunk does not play any kinematic role. Its purpose is only to include the psoas muscles connected to the leg. So we should simply set it to a fix position.
The trunk has three free rotations, flexion, lateral bending and axial rotation plus the rotation of the skull that we will fix to zero degree. This can be done by a so-called
simple driver. In the JointsAndDrivers file we shall introduce a driver section below the Joints folder:

AnyFolder Joints = {
AnyStdJoint SeatPelvis = {
AnyRefNode &Seat = Main.MyPedal.EnvironmentModel.GlobalRef.Hpoint;
AnySeg &Pelvis = Main.MyPedal.HumanModel.Trunk.SegmentsLumbar.PelvisSeg;
};
};
AnyFolder Drivers = {
};

We then insert two simple drivers into the Drivers folder:

AnyFolder Drivers = {
AnyKinEqSimpleDriver PostureDriver ={
AnyKinMeasureOrg &Ref2 = ...HumanModel.Interface.Trunk.PelvisThoraxLateralBending;
AnyKinMeasureOrg &Ref3 = ...HumanModel.Interface.Trunk.PelvisThoraxRotation;
AnyKinMeasureOrg &Ref1 = ...HumanModel.Interface.Trunk.PelvisThoraxExtension;

DriverPos = {0,0,0};
DriverVel = {0,0,0};
};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 188 of 229

AnyKinEqSimpleDriver NeckJntDriver = {
AnyRevoluteJoint &T12L1Joint = ...HumanModel.Interface.Trunk.NeckJoint;
DriverPos = {0};
DriverVel = {0};
};

};

Most of this came about the same way as we have done previously: The definition of the AnyKinEqSimpleDriver (and indeed its complex name) came from the object
inserter in the Classes tree at the left hand side of the editor window. The complete name of the thorax and neck rotations was inserted from the object tree. The joints are
going to be static and in their neutral position, so the DriverVel and DriverPos are simply zero .

3. Connecting the foot to the pedal

The foot will be connected to the pedal by a spherical joint. This is defined inside the JointsAndDrivers file in the following way:

AnySphericalJoint PedalFoot = {
AnyRefNode &Pedal = Main.MyPedal.EnvironmentModel.Pedal.FootNode;
AnyRefNode &Foot = Main.MyPedal.HumanModel.Right.Leg.Seg.Foot.MetatarsalJoint2Node;
};

We have cheated just a little. It is possible to define new nodes on the foot for attachment to a specific place, but we have taken the cheap-and-dirty solution of picking an
existing point close to where we presume the contact with the pedal will be. The MetatarsalJoint2Node is a good approximation.

4. Setting the ankle angle

The ankle in this body model is a universal joint, which means that it has two degrees of freedom. We wish to constrain these to degrees of freedom to predefined values.
This can be done by the simple driver. We shall introduce the simple driver into the Drivers folder:

AnyFolder Drivers = {
AnyKinEqSimpleDriver PostureDriver ={
AnyKinMeasureOrg &Ref2 = ...HumanModel.Interface.Trunk.PelvisThoraxLateralBending;
AnyKinMeasureOrg &Ref3 = ...HumanModel.Interface.Trunk.PelvisThoraxRotation;
AnyKinMeasureOrg &Ref1 = ...HumanModel.Interface.Trunk.PelvisThoraxExtension;

DriverPos = {0,0,0};
DriverVel = {0,0,0};
};
AnyKinEqSimpleDriver NeckJntDriver = {
AnyRevoluteJoint &T12L1Joint = ...HumanModel.Interface.Trunk.NeckJoint;
DriverPos = {0};
DriverVel = {0};
};

AnyKinEqSimpleDriver AnkleDriver = {
AnyUniversalJoint &Ankle = Main.MyPedal.HumanModel.Right.Leg.Jnt.Ankle;
DriverPos = {};
DriverVel = {0, 0};
};

};

Like before the driver and joint name are inserted from the model three. This time what is remaining is the DriverPos specification. It is currently an empty pair of braces.
The problem here is to know which of the two degrees of freedom is which. Fortunately, the model is already loaded, and we can get the current values for the ankle angles
from the object tree. Click your way through the tree to HumanModel->BodyModel->Right->Leg->Jnt->Ankle, and double-click the Pos property. The current angles are
dumped in the message window:

Main.MyPedal.HumanModel.Right.Leg.Jnt.Ankle.Pos = { 1.226519, -0.265366 };

Now we know which value to assign to the joint angle driver:

AnyFolder Drivers = {
AnyKinEqSimpleDriver AnkleDriver = {
AnyUniversalJoint &Ankle = Main.MyPedal.HumanModel.Right.Leg.Jnt.Ankle;
DriverPos = {1.226519, -0.265366};
DriverVel = {0, 0};
};

};

The model should load again with no significant difference.

5. Fix the lateral position of the knee

Imagine your pelvis on a seat and your foot resting on a point like the model is right now. You can still move your knee sideways either medially or laterally rotating the
leg about an axis through the foot contact point and the hip joint. We must constrain this movement, and the easiest way to do it is by fixing the knee laterally.

We shall do this by another simple driver in conjunction with a linear measure. Let us add another driver to the Drivers folder:

AnyFolder Drivers = {
AnyKinEqSimpleDriver PostureDriver ={
AnyKinMeasureOrg &Ref2 = ...HumanModel.Interface.Trunk.PelvisThoraxLateralBending;
AnyKinMeasureOrg &Ref3 = ...HumanModel.Interface.Trunk.PelvisThoraxRotation;
AnyKinMeasureOrg &Ref1 = ...HumanModel.Interface.Trunk.PelvisThoraxExtension;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 189 of 229

DriverPos = {0,0,0};
DriverVel = {0,0,0};
};
AnyKinEqSimpleDriver NeckJntDriver = {
AnyRevoluteJoint &T12L1Joint = ...HumanModel.Interface.Trunk.NeckJoint;
DriverPos = {0};
DriverVel = {0};
};

AnyKinEqSimpleDriver AnkleDriver = {
AnyUniversalJoint &Ankle = Main.MyPedal.HumanModel.Right.Leg.Jnt.Ankle;
DriverPos = {1.570796, 0};
DriverVel = {0, 0};
};

AnyKinEqSimpleDriver KneeDriver = {
DriverPos = {0};
DriverVel = {0};
};
};

This empty driver needs something to drive. We are going to create a linear measure between the global reference frame and the knee:

AnyKinEqSimpleDriver KneeDriver = {
AnyKinLinear GlobKnee = {
AnyRefFrame &Glob = Main.MyPedal.EnvironmentModel.GlobalRef;
AnyRefFrame &Knee = Main.MyPedal.HumanModel.Right.Leg.Seg.Thigh.KneeJoint;
};
DriverPos = {0};
DriverVel = {0};
};
};

The AnyKinLinear is really a vector between the two points it refers to, i.e. in this case the position of the knee in the global reference frame. However, we only wish to
drive one of the coordinates of this vector, namely the lateral coordinate. This is the z coordinate, which in an AnyScript model has number two, because numbering begins
at 0. To drive only this one coordinate, we insert a measure organizer:

AnyKinEqSimpleDriver KneeDriver = {
AnyKinLinear GlobKnee = {
AnyRefFrame &Glob = Main.MyPedal.EnvironmentModel.GlobalRef;
AnyRefFrame &Knee = Main.MyPedal.HumanModel.Right.Leg.Seg.Thigh.KneeJoint;
};
MeasureOrganizer = {2};
DriverPos = {0};
DriverVel = {0};
};
};

This has the effect of neglecting the x and y coordinates of the vector returned by the linear measure. You should be able to load the model again, but there is no visible
difference.

6. Drive the pedal

The final step is to drive the movement of the pedal. It is hinged to the origin of the coordinate system, and we shall add a driver to the joint angle pretty much like we did
with the ankle and the knee.

AnyKinEqSimpleDriver KneeDriver = {
AnyKinLinear GlobKnee = {
AnyRefFrame &Glob = Main.MyPedal.EnvironmentModel.GlobalRef;
AnyRefFrame &Knee = Main.MyPedal.HumanModel.Right.Leg.Seg.Thigh.KneeJoint;
};
MeasureOrganizer = {2};
DriverPos = {0};
DriverVel = {0};
};

AnyKinEqSimpleDriver Pedal = {
AnyRevoluteJoint &Hinge = Main.MyPedal.EnvironmentModel.HingeJoint;
DriverPos = {100*pi/180};
DriverVel = {45*pi/180};
};

This puts the pedal in an initial 100 degree angle compared to vertical. It also specifies a movement with an angular velocity of 45 degrees per second, but let us postpone
the investigation of that for later.

For now, hit F7 again to reload the model. Notice that the system no longer complains about the model being kinematically indeterminate. Run the SetInitialConditions
operation to get things connected. With a little luck you will get this picture:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 190 of 229

With the model kinematically determinate we can proceed and run the KinematicAnalysis operation. Doing so will show you the movement of the entire system as the
pedal is rotating.

Now that the kinematics is in order, let us move on to the kinetic analysis in Lesson 8 and see what the model is good for.

Lesson 8: Kinetics - Computing Forces


With the kinematic analysis in place we are ready to compute forces and investigate ergonomic properties of the pedal arrangement. We shall presume that the pedal is
loaded by a spring, the force of which the leg must overcome when stepping on the pedal. AnyScript has a ligament class, which can be used to create springs of various
types. Please refer to the ligament tutorial for further information. However, here we shall take a simpler approach and simply define the spring force directly.

A force can be added to any kinematic measure by means of the AnyForce class. Because the concept of kinematic measures is general, the AnyForce class attains the type
given by the kinematic measure. If the measure is a length, then an AnyForce is a force, and if it is an angle, the AnyForce automatically becomes a moment. In the present
case we shall add the AnyForce to the kinematic measure of the pedal's hinge. Let us initially study the measure. Run the KinematicAnalysis again, open a ChartFX
2D View, and browse your way through the tree to
Main.MyStudy.Output.Model.EnvironmentModel.HingeJoint.Pos. You should see the following graph:

The analysis runs in time from zero to one second, and the pedal angle develops in this time from 100 degrees (1.74 rad) to 145 degrees (2.53 rad). Let us presume that the
pedal is loaded by a linear spring that is slack at 0 degrees and increases its moment linearly with the rotation of the hinge. We might be wondering: What would be a
comfortable spring stiffness for a pedal like that? Not having much experience with pedal design it might be difficult to imagine just how stiff the spring should be, and we
could find ourselves developing a series of hardware prototypes with different springs and perhaps conducting subjective investigations with test subjects. A simple task
like this could potentially be very time consuming and expensive.

Let us do it with AnyBody instead. We shall start out by declaring an AnyForce to play the role of the spring. Since this is not a part of the body it is logical to place it in
the Environment.any file. Here's what to add:

AnyRevoluteJoint HingeJoint = {
Axis = z;
AnyFixedRefFrame &Ground = .GlobalRef;
AnyRefNode &Pedal = .Pedal.Hinge;
};
AnyForce Spring = {
AnyRevoluteJoint &Hinge = .HingeJoint;
F = -0.0*.HingeJoint.Pos;
};

This looks easy, does it not? The AnyForce contains a reference to the HingeJoint. Since the degree of freedom in HingeJoint is rotational, the force is automatically turned
into a moment and applied it to the hinge. The specification of F is the actual size of the force. We have made it proportional to the HingeJoint.Pos, which is the hinge
angle, and we have initially set the spring stiffness to 0.0, to investigate the effect of having no spring before we start adding a spring force. Notice, by the way, the minus
sign in front of spring constant. It has no importance now, but when we start adding non-zero stiffnesses it will signify that the spring force goes against the angle, i.e.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 191 of 229

pushes back onto the foot.

There are just a couple of things we need to do before we can do the InverseDynamicAnalysis operation and compute the forces: All the drivers we added in the previous
lesson have motors built into them. This means that whatever force or moment is necessary to perform the movement will be provided by the drivers, and there will be
nothing for the muscles to do. Motors in drivers are technically reaction forces, and they can be turned off inside the driver:

AnyFolder Drivers = {
AnyKinEqSimpleDriver PostureDriver ={
AnyKinMeasureOrg &Ref2 = ...HumanModel.Interface.Trunk.PelvisThoraxLateralBending;
AnyKinMeasureOrg &Ref3 = ...HumanModel.Interface.Trunk.PelvisThoraxRotation;
AnyKinMeasureOrg &Ref1 = ...HumanModel.Interface.Trunk.PelvisThoraxExtension;

DriverPos = {0,0,0};
DriverVel = {0,0,0};
Reaction.Type = {Off, Off, Off};
};

AnyKinEqSimpleDriver NeckJntDriver = {
AnyRevoluteJoint &T12L1Joint = ...HumanModel.Interface.Trunk.NeckJoint;
DriverPos = {0};
DriverVel = {0};
Reaction.Type = {Off};
};

AnyKinEqSimpleDriver AnkleDriver = {
AnyUniversalJoint &Ankle = Main.MyPedal.HumanModel.Right.Leg.Jnt.Ankle;
DriverPos = {1.570796, 0};
DriverVel = {0, 0};
Reaction.Type = {Off, Off};
};
AnyKinEqSimpleDriver KneeDriver = {
AnyKinLinear GlobKnee = {
AnyRefFrame &Glob = Main.MyPedal.EnvironmentModel.GlobalRef;
AnyRefFrame &Knee = Main.MyPedal.HumanModel.Right.Leg.Seg.Thigh.KneeJoint;
};
MeasureOrganizer = {2};
DriverPos = {0};
DriverVel = {0};
Reaction.Type = {Off};
};

AnyKinEqSimpleDriver Pedal = {
AnyRevoluteJoint &Hinge = Main.MyPedal.EnvironmentModel.HingeJoint;
DriverPos = {100*pi/180};
DriverVel = {45*pi/180};
Reaction.Type = {Off};
};

There is one more thing we have to do: The model has no muscles. This can be rectified by a simple change in the BodyPartsSetup file:

// Trunk: 1 included, 0 not included


// *********************************
#define TRUNK 1
// This is just the bones,
// Choose one of the following options to add muscles
#define TRUNK_SIMPLE_MUSCLES 1

...

// RightLeg: 1 included, 0 not included


// ************************************
#define RIGHT_LEG 1
// This is just the bones,
// Choose one of the following options to add muscles
#define RIGHT_LEG_SIMPLE_MUSCLES 1
#define RIGHT_LEG_MUS_3E 0

Now, reload the model and run the InverseDynamicAnalysis. The model should look like this:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 192 of 229

Notice that the muscle forces are illustrated by the bulging of the muscles. In the ChartFx view near the top of the tree you can find the MaxMuscleActivity. It expresses
the load on the body in percent of its strength. Plotting this property in the ChartFx View gives you the following result:

Obviously holding the leg out in the air like that without the support of a pedal spring and holding up the weight of the pedal as well is rather strenuous and in fact requires
about 54% of the body's strength.

Now, let us study the effect of spring stifness. We initially try:

F = -10*.HingeJoint.Pos;

This produces the activity curve:

Obviously the level is much lower now starting at just 16%, so the spring really seems to help. Let us try to double the stiffness:

F = -20*.HingeJoint.Pos;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 193 of 229

This appears to be equally good in terms of activity level and has the added quality of increasing muscle activity or effort for increasing angle. This can make it easier for
the operator to control the pedal and thereby enhance the operability.

The completed model is available here: PedalDemo.zip .

The AnyBody Modeling System is all about making this type of investigation easy. The mechanical model we have put together in four simple lessons has a complexity
worthy of a Ph.D. project if you develop it bottom up. In AnyBody, this is a matter of a few hours of work when using the predefined models of the repository.

Let's continue to Lesson 9: Model Structure .

Lesson 9: Model Structure


This section contains recommendations on construction of body parts to make them compatible with the model structure of the AnyScript Managed Model Repository.

Building an AnyScript model of a body part or the complete body is much like any other complex construction work in the sense that it requires planning and coordination.
This is particularly true if different people divide the task between them and later assemble the model. These are the general recommendations:

The Repository uses the ISB coordinate system.

The International Society of Biomechanics is endorsing the use of a particular convention for coordinate axes in the human body, and so are we. These recommendations
are published in these references:

Wu G, Cavanagh PR.: ISB recommendations for standardization in the reporting of kinematic data. J Biomech 1995 Oct;28(10):1257-1261

Wu G, Siegler S, Allard P, Kirtley C, Leardini A, Rosenbaum D, Whittle M, D'Lima DD, Cristofolini L, Witte H, Schmid O, Stokes I.: ISB recommendation on definitions
of joint coordinate system of various joints for the reporting of human joint motion-part I: ankle, hip, and spine. J Biomech 2002 Apr;35(4):543-548.

Conventions like these are always debatable. For instance, ISB recommends a vertical y axis, where many users probably feel that a vertical z axis is natural But there is a
distinct benefit to having a standard, so most of the models in the repository adhere to the ISB recommendation.

The Repository uses SI Units

SI units are based on meters, kilograms and seconds. They are consistent and therefore eliminate the possibility of miscalculations due to hidden conversion factors. For
instance, a seemingly consistent use of millimeters instead of meters in a model may lead to the devious error of square root 1000 in some types of calculations. The
AnyBody Modeling System expects all angles to be specified in radians. If you feel more comfortable working with degrees you can use expressions to convert to radians
like this example where we specify an angle of 30 degrees:

AnyVar KneeAngle = 30*Pi/180;

Bodies and environments

When you load a model from the repository and investigate its tree, you will find that it is structured with one folder for the body parts (HumanModel), one folder for the
environment (EnnvironmentModel), and one folder for the connection between the human model and the environment (ModelEnvironmentConnection).

The idea behind this system is to make the human model and the environment model as independent of each other as possible.

Some models also have a folder called Mannequin for control of posture.

Scaling
Musculoskeletal models must be scalable to sizes of different individuals to be useful for product design. This is very challenging, because scaling pertains not only to the
overall geometry, but also to properties like muscle insertion points, muscle parameters and wrapping surfaces. A general method for scaling musculoskeletal models has
been implemented into the AnyBody Respository models. The scaling procedure is implemented in a generic manner and allows the usage of user-defined scaling laws. For
details on the theory behind please take a look at the scaling introduction presented by AnyBody researchers in cooperation with researchers from Ford: Abstract and
Poster .

The models in the AnyBody Managed Model Repository have been made scalable by building generalized parameters into all the numbers in the model. Just about
everywhere, numbers in the models have been replaced by calls to a scaling law. This means that all body models expect such a scaling law to be present, but it is up to the
user to choose the actual law. This decoupling of the scaling laws from the body parts makes it possible for the user to choose between the laws that are supplied with the
models or perhaps define a new law, without making any changes in the body models.

Currently there are seven scaling laws available in AnyBody

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 194 of 229

 ScalingStandard (do not scale; i.e. use standard model size)


 ScalingUniform (scale equally in all directions; input is joint to joint distances)
 ScalingLengthMass (scale taking mass into account; input is joint to joint distances and mass)
 ScalingLengthMassFat (scale taking mass and fat into account; input is joint to joint distances)
 ScalingUniformExt (scale equally in all directions; input is external measurements)
 ScalingLengthMassExt (scale taking mass into account; input is external measurement)
 ScalingLengthMassFatExt (scale taking mass and fat into account; input is external measurements).

The parameters of the scaling laws are controlled by the mean of the AnyMan.any file. Several versions of this file are available the choice depending on the scaling
strategy chosen. More details about how to use this file are given along the tutorial.

Please also notice that each scaling law scales the strength of the muscles, in addition to the size and mass of the bone. This strength scaling is done automatically in most
cases. We will come back to it when needed. Users who need a more comprehensive introduction can view this recorded previous webcast entitled “Anthropometrical
Scaling of Musculoskeletal Models” .

The first four scaling methods are covered in Lesson 1. They are often referred to as Joint to joint scaling methods. Lesson 2 covers the latter three which are based on
external body measurement.

With the AnyBody Modeling System you already have a repository of models available, for details please see the AnyBody Assistant available from the menu. As a
starting point for this tutorial please find the model StandingModelScalingDisplay. This model can be found in the folder Applications/Examples. This tutorial has been
written using the AnyBody Managed Model Repository Ver. 1.1 (AMMRV1.1) if you see differences between the tutorial text and your own results please download
AMMRV1.1 from http://forge.anyscript.org/gf/project/ammr/frs/

Now head on for Lesson 1: Joint to joint scaling methods .

Lesson 1: Joint to joint scaling methods


This lesson covers four of the scaling laws available in AnyBody

 ScalingStandard (do not scale)


 ScalingUniform (scale equally in all directions; input is joint to joint distances)
 ScalingLengthMass (scale taking mass into account input is joint to joint distances and mass)
 ScalingLengthMassFat (scale taking mass and fat into account; input is joint to joint distances)

ScalingStandard

This scaling law produces a model with default parameters for mass and size (corresponding roughly to the 50th percentile European male). It is used by default for non-
specific models, or when there is no data available about the modeled subject. This law does not use the AnyMan file because there is no parameter to modify.

With the AnyBody Modeling System you already have a repository of models available, for details please see the AnyBody Assistant available from the menu, so let’s
practice1, as a starting point for this tutorial please find the model

Model/Application/Examples/StandingModelScalingDisplay/StandingModelScaling.main.

This tutorial has been written using the AnyBody Managed Model Repository Ver. 1.1 (AMMRV1.1) if you see differences between the tutorial text and your own results
please download AMMRV1.1 from http://forge.anyscript.org/gf/project/ammr/frs/

To use this law choose the include file ScalingStandard.any in the Main file you just opened as following:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 195 of 229

// This section below offers the choice between


// several scaling strategies
#include "..\..\..\Body\AAUHuman\Scaling\ScalingStandard.any"

// Scaling laws using joint to joint measures


//#include "..\..\..\Body\AAUHuman\Scaling\ScalingUniform.any"
//#include "..\..\..\Body\AAUHuman\Scaling\ScalingLengthMass.any"
//#include "..\..\..\Body\AAUHuman\Scaling\ScalingLengthMassFat.any"
// Scaling laws using external measures
//#include "..\..\..\Body\AAUHuman\Scaling\ScalingUniformExt.any"
//#include "..\..\..\Body\AAUHuman\Scaling\ScalingLengthMassExt.any"
//#include "..\..\..\Body\AAUHuman\Scaling\ScalingLengthMassFatExt.any"
//#include "DrawExternalMeasures.any"
Scaling = {
//#include "..\..\..\Body\AAUHuman\Scaling\AnyFamily\AnyMan.any"
//#include "..\..\..\Body\AAUHuman\Scaling\AnyFamily\AnyManUniform.any"
//#include "..\..\..\Body\AAUHuman\Scaling\AnyFamily\AnyManExternal.any"
//#include "..\..\..\Body\AAUHuman\Scaling\AnyFamily\AnyManExtPercentile.any"
//#include "..\..\..\Body\AAUHuman\Scaling\AnyFamily\AnyWomanExtPercentile.any"
};

Now load the model and open a ModelView window, you will see the standing model with the standard size.

ScalingUniform

This law allows you to define the total weight of the model and the individual sizes of the bones. The length of each bone is defined as a joint to joint distance and the bone
is then scaled in three dimensions proportionally to its length. To use this law you must include the ScalingUniform.any file with the AnyMan.any file in the Main:

// This section below offers the choice between several scaling strategies
//#include "..\..\..\Body\AAUHuman\Scaling\ScalingStandard.any"
// Scaling laws using joint to joint measures
#include "..\..\..\Body\AAUHuman\Scaling\ScalingUniform.any"
//#include "..\..\..\Body\AAUHuman\Scaling\ScalingLengthMass.any"
//#include "..\..\..\Body\AAUHuman\Scaling\ScalingLengthMassFat.any"
...
Scaling = {
#include "..\..\..\Body\AAUHuman\Scaling\AnyFamily\AnyMan.any"
//#include "..\..\..\Body\AAUHuman\Scaling\AnyFamily\AnyManUniform.any"
...
};

AnyMan.any is the file in which you can modify the mass and size parameters. We will now try to use it. Please load the model and have a look at the ModelView window.
Notice that the body size did not change from the ScalingStandard version. This is because the default values for segment masses and sizes in this file are the same as the
standard values. But if you change them the model will scale according to your specifications.
Double click on the line #include "..\..\..\Body\AAUHuman\Scaling\AnyFamily\AnyMan.any" to open the AnyMan file and have a closer look at it. The total body weight
is expressed in kilograms by the variable Body_Mass at the top of the file:

AnyVar Body_Mass = 75 ;

Try changing it to 90 kg and load the model again. Once again the size of the body did not change. In the ScalingUniform law, the Body_Mass parameter controls the mass
of the segments but not their sizes. Further down in the AnyMan file you can see that the Body_Mass parameter is distributed to the segments according to some
coefficients:

//Segment masses in kg from Winter ("Biomechanics and motor control of human movement." David A. Winter)
AnyVar lumbar = 0.139*Body_Mass; // T12-L1 to L5-Sacrum
AnyVar thorax = 0.1894*Body_Mass; // C7-T1 to T12-L1 (modified from 0.216 Winter to separate scapula)
AnyVar pelvis = 0.142*Body_Mass;
AnyVar clavicle_r = 0.0133*Body_Mass;
AnyVar upper_arm_r = 0.028*Body_Mass;
AnyVar lower_arm_r = 0.016*Body_Mass;
AnyVar hand_r = 0.006*Body_Mass;
AnyVar clavicle_l = 0.0133*Body_Mass;
AnyVar upper_arm_l = 0.028*Body_Mass;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 196 of 229

AnyVar lower_arm_l = 0.016*Body_Mass;


AnyVar hand_l = 0.006*Body_Mass;
AnyVar head = 0.081*Body_Mass; // head and cervical
AnyVar thigh_r = 0.1*Body_Mass;
AnyVar lower_leg_r = 0.0465*Body_Mass;
AnyVar foot_r = 0.0145*Body_Mass;
AnyVar ball_r = 0.000;
AnyVar thigh_l = 0.1*Body_Mass;
AnyVar lower_leg_l = 0.0465*Body_Mass;
AnyVar foot_l = 0.0145*Body_Mass;
AnyVar ball_l = 0.000;

So the Body_Mass parameter only controls the segment masses. The size of the model is controlled by another list of variables defining the lengths of the different bones:

AnyFolder AnthroSegmentLengths = {
AnyVar ThighLength = 0.45579;
AnyVar ShankLength = 0.46;
AnyVar FootLength = 0.200771;
AnyVar PelvisWidth = 0.16;
//distance between hip joints
AnyVar HeadHeight = 0.14;
//height in neutral position from C1HatNode to top of head
AnyVar TrunkHeight = 0.620233;
//height in neutral position from C1HatNode to L5SacrumJnt
AnyVar UpperArmLength = 0.340079;
AnyVar LowerArmLength =0.2690167;
};

The length of each segment can be set independently, for example we can increase the length of the thigh by modifying this line:

AnyVar ThighLength = 0.626;

Load the model again and have a look at the Model View window. The femur bone is now bigger. It has been scaled uniformly in 3 directions according to the defined
length. Notice that we only changed the size of the femur and not the other bones, so the femur looks unreasonably big compared to the rest of the body. To avoid results
such as this it is important to feed those variables with consistent data rooted in real anthropometry.

Let us apply a more reasonable size. Please change the default values to the following set of consistent measures:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 197 of 229

AnyFolder AnthroSegmentLengths = {
AnyVar ThighLength = 0.548;
AnyVar ShankLength = 0.551;
AnyVar FootLength = 0.243;
AnyVar PelvisWidth = 0.180;
//distance between hip joints
AnyVar HeadHeight = 0.169;
//height in neutral position from C1HatNode to top of head
AnyVar TrunkHeight = 0.754;
//height in neutral position fromC1HatNode to L5SacrumJnt
AnyVar UpperArmLength = 0.405;
AnyVar LowerArmLength =0.316;
};

When you reload the model you should see a tall body and with proportionate sizes of the segments. If you can't see the difference from the standard size model notice how
the feet are now sticking down below the reference frame.

It should be obvious that this type of scaling requires good anthropometric data to give reasonable results. But such data is not always easily available. So there is a version
of the AnyMan file called AnyManUniform.any. This file only takes as input the body mass and the body height and subsequently scales all the segment lengths uniformly
according to the defined body height. This may not give you a model where each bone matches a given subject, but it can be a reasonable estimate in cases where only the
overall mass and height of the body is known. Try including the AnyManUniform.any file:

Scaling = {
//#include "..\..\..\Body\AAUHuman\Scaling\AnyFamily\AnyMan.any"
#include "..\..\..\Body\AAUHuman\Scaling\AnyFamily\AnyManUniform.any"
...
};

Now it is easy to scale the body down to represent a small person. Open the AnyManUniform file and change the mass and height variable as following:

AnyFolder AnthroData = {
AnyVar Body_Mass = 60;
AnyVar body_height = 165/100;

When you load the model you will see all the segments automatically scaling down. The mass is also scaled, but as we said previously this is not visible graphically with
this scaling law.

ScalingLengthMass

This law scales the size of the body according not only to the segment lengths but also to the segments masses, so unlike the ScalingUniform law it provides the
opportunity to define tall and skinny people or small and squat people. Like in the ScalingUniform law, the total body mass is defined by the variable Body_Mass. Just as
previously, this total mass is then divided between the segments by means of coefficients, but the size scaling is different. Let’s investigate it. In the main file, please
choose the ScalingLengthMass law and switch back to the AnyMan file:

// Scaling laws using joint to joint measures


//#include "..\..\..\Body\AAUHuman\Scaling\ScalingUniform.any"
#include "..\..\..\Body\AAUHuman\Scaling\ScalingLengthMass.any"
//#include "..\..\..\Body\AAUHuman\Scaling\ScalingLengthMassFat.any"

Scaling = {
#include "..\..\..\Body\AAUHuman\Scaling\AnyFamily\AnyMan.any"
//#include "..\..\..\Body\AAUHuman\Scaling\AnyFamily\AnyManUniform.any"
...
};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 198 of 229

In the AnyMan file, switch back the segment length values to the initial ones and increase the body mass to 110 kg:

AnyVar Body_Mass = 110;


...
AnyFolder AnthroSegmentLengths = {
AnyVar ThighLength = 0.45579;
AnyVar ShankLength = 0.46;
AnyVar FootLength = 0.200771;
AnyVar PelvisWidth = 0.16;
//distance between hip joints
AnyVar HeadHeight = 0.14;
//height in neutral position from C1HatNode to top of head
AnyVar TrunkHeight = 0.620233;
//height in neautral position from C1HatNode to L5SacrumJnt
AnyVar UpperArmLength = 0.340079;
AnyVar LowerArmLength = 0.2690167;
};

Load the model and look at the ModelView. Our model looks strange! The body is deformed and looks a bit like a Neanderthal.

What really happens is that the ScalingLengthMass law scales the sizes of the segments according to their masses, but only in two directions. The third scaling direction is
controlled by the segment length variables. Unlike in the ScalingUniform law, the segment length variables just control one scaling direction and not the two others.

So to have a normal-looking model we have to adjust segment mass and length simultaneously. As the mass we defined is 110 kg, a height of 1.98 m could be reasonable.
As we don’t have a clear idea of the individual segment lengths, we shall simply multiply all of them by a single coefficient (it is also a good opportunity to use the
AnyManUniform file and directly enter the 1.98 m height, you can try it). The initial segment lengths correspond to a body of 1.80 m so the ratio we are going to multiply
the segment length with is 1.1:

AnyFolder AnthroSegmentLengths = {
AnyVar ThighLength = 0.45579*1.1;
AnyVar ShankLength = 0.46*1.1;
AnyVar FootLength = 0.200771*1.1;
AnyVar PelvisWidth = 0.16*1.1;
//distance between hip joints
AnyVar HeadHeight = 0.14*1.1;
//height in neutral position from C1HatNode to top of head
AnyVar TrunkHeight = 0.620233*1.1;
//height in neautral position from C1HatNode to L5SacrumJnt
AnyVar UpperArmLength = 0.340079*1.1;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 199 of 229

AnyVar LowerArmLength =0.2690167*1.1;


};

When you load the model you will see a more Homo sapiens -looking figure corresponding to a large 110kg and 1.98 m person.

We mentioned at the beginning of the tutorial that the muscle strength is also scaled. It is time to have a look at it and compare muscle forces from different scaled models.
To do so we need a body with muscles. Please include the body model with muscles this way:

// Use only ONE of the three include files below at any time
// --------------------------------------------------------
// Selecting the include file below results in a body model without muscles.
// Instead, the model is equipped with joint moment providers. This version
// loads and run much faster than versions with anatomical muscles.
// #include "..\..\..\Body\AAUHuman\BodyModels\FullBodyModel\BodyModel_NoMuscles.any"
// Selecting the include file below results in a body model with simple
// constant stength muscles. They are adequate for many purposes and have the
// advantage of not requiring calibration
#include "..\..\..\Body\AAUHuman\BodyModels\FullBodyModel\BodyModel.any"
// The include file below selects the three-element Hill-type muscles.
// They require calibration before they can be used, and this can be done
// by the HumanModel.Calibration.CalibrationSequence operation. This must
// be executed every time the model is reloaded.
//#include "..\..\..\Body\AAUHuman\BodyModels\FullBodyModel\BodyModel_Mus3E.any"

We also need to add some forces to model in order to make it react and see some muscle activity. This can be done by adding those lines in the Environment.any file. This
piece of code creates a force of 50 N on each hand and display it in the model view:

AnyFolder EnvironmentModel = {

/* **********************************************************
This folder contains the definition of the Environment
- GlobalRefFrame

********************************************************** */

AnyFixedRefFrame GlobalRef = {
Origin ={0.0,0.0,0.0};
#include "drawcoorsystem.any"
AnyDrawRefFrame drw={};
};//GlobalRef

AnyForce3D RightHandLoad = {
F = {0, -50, 0};
AnyRefFrame &Hand = Main.HumanModel.BodyModel.Right.ShoulderArm.Seg.Glove;
};

AnyForce3D LeftHandLoad = {
F = {0, -50, 0};
AnyRefFrame &Hand = Main.HumanModel.BodyModel.Left.ShoulderArm.Seg.Glove;
};

AnyDrawVector DrawRightLoad = {
Vec = .RightHandLoad.F*0.015;
PointAway = On;
GlobalCoord = On;
Line = {
Style = Line3DStyleFull;
Thickness = 0.01;
RGB = {0, 0, 0};
End = {
Style = Line3DCapStyleArrow;
RGB = {0, 0, 0};
Thickness = 0.025;
Length = 0.025;
};
};
AnyRefFrame &Hand = .RightHandLoad.Hand;
};

AnyDrawVector DrawLeftLoad = {
Vec = .LeftHandLoad.F*0.015;
PointAway = On;
GlobalCoord = On;
Line = {
Style = Line3DStyleFull;
Thickness = 0.01;
RGB = {0, 0, 0};
End = {
Style = Line3DCapStyleArrow;
RGB = {0, 0, 0};
Thickness = 0.025;
Length = 0.025;
};
};
AnyRefFrame &Hand = .LeftHandLoad.Hand;
};

};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 200 of 229

We are now ready to run an inverse dynamic analysis with our large 110kg model. Please load the model and run the InverseDynamicAnalysis from the operation tree.
Then open a new ChartFX window to investigate the results. By browsing your way to the MaxMuscleActivity output you should get this:

We will now try to model a small person to compare his muscle activity with the one we have just plotted. In the AnyMan file let’s enter the parameters for a 65kg and 1.70
m person:

AnyVar Body_Mass = 65 ;

AnyFolder AnthroSegmentLengths = {
AnyVar ThighLength = 0.45579*0.95;
AnyVar ShankLength = 0.46*0.95;
AnyVar FootLength = 0.200771*0.95;
AnyVar PelvisWidth = 0.16*0.95; //distance between hip joints
AnyVar HeadHeight = 0.14*0.95;//height in neutral position from C1HatNode to top of head
AnyVar TrunkHeight = 0.620233*0.95;//height in neutral position from C1HatNode to L5SacrumJnt
AnyVar UpperArmLength = 0.340079*0.95;
AnyVar LowerArmLength =0.2690167*0.95;
};

We can load the model, run a new InverseDynamicAnalysis and investigate the results in the ChartFX window.

For the same load on the hands (50 N) the tall heavy model has a muscle activity of 30.8 % whereas the short model reaches 42.3 % of muscle activity. So our small model
is definitely weaker than the tall one.

ScalingLengthMassFat

Most scaled models used for practical investigations use the ScalingLengthMassFat law. It works exactly like the ScalingLengthMass but with an additional parameter: It
takes the fat percentage of the body into account. The argument is that the fat percentage adds to the mass of each segment and in the ScalingLengthMass law would lead
an estimation of more muscle tissue rather than fat tissue. So the fat percentage in this scaling model does not modify the mass or the size of the body. It is only used to
calculate the strength of the muscles. Between two persons of similar segment masses, the one with higher fat percentage will have less muscle strength because the
volume otherwise occupied by the muscles is replaced by inactive fat.

So the mass and size scales are controlled as in the ScalingLengthMass model by the Body_Mass variable and all the segment length variables respectively. The fat
percentage is controlled in concert by the variables Body_Height and Body_Mass. These two variables are used to calculate the BMI (Body-Mass Index), and the BMI is

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 201 of 229

used to calculate the fat percentage of the body according to Frankenfield, D. C.; Rowe, W. A.; Cooney, R. N.; Smith, J. S. & Becker, D. (2001): Limits of body mass
index to detect obesity and predict body composition, Nutrition 17(1), 26-30.

AnyVar BMI = AnthroData.Body_Mass/(AnthroData.body_height^2);


AnyVar FatPercent = (-0.09 + 0.0149*BMI - 0.00009*BMI^2)*100;
//Estimation from Frankenfield et al. (2001) valid for men

Obviously it is important to input the correct height of the body when using this law. Please notice, however, that it is very easy for the user to substitute the formula for the
fat percentage by another equation or possibly by a fixed number for modeling of a particular individual for whom the fat percentage has been measured directly.

The resulting value for the fat percentage is then directly used to compute an estimate of the strength of each muscle in the model.

This advanced strength scaling makes of course a particular difference for model that is short and heavy. The ScalingLengthMass law tends to over-estimate the strength of
those models because they are often corresponding to a high fat percentage that is not taken into account by the law.

We will try to illustrate this by plotting the muscle activity of the same short and heavy model with both ScalingLengthMass and ScalingLengthMassFat laws. We will
begin by adjusting the AnyMan file by to fit a 85kg and 1.70 m person:

AnyVar Body_Mass = 85;

Then please load the model and run an InverseDynamicAnalysis. Notice that we should still be using the ScalingLengthMass law. You should now get the following graph
for the maximum muscle activity.

The next step is to run an analysis with the same body but with the ScalingLengthMassFat law:

// Scaling laws using joint to joint measures


//#include "..\..\..\Body\AAUHuman\Scaling\ScalingUniform.any"
//#include "..\..\..\Body\AAUHuman\Scaling\ScalingLengthMass.any"
#include "..\..\..\Body\AAUHuman\Scaling\ScalingLengthMassFat.any"

Once again load the model an run the InverseDynamicAnalysis. We should get the following results:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 202 of 229

If we compare the two activity graph the difference is clear. The ScalingLengthMassFat law is increasing the muscle activity of almost 10 % in this case, from 31 % to 39
%. This shows the limits of the ScalingLengthMass law for extreme cases. ScalingLengthMassFat is able to cover a wider range of cases while keeping its accuracy.

Just like the ScalingLengthMass law this law can also be used with the AnyManUniform file.

This completes scaling Lesson 1: Joint to joint scaling methods.

Now move on to Lesson 2: Scaling based on external body measurements.

Lesson 2: Scaling based on external body measurements


This tutorial presumes that you have completed Scaling tutorial Lesson 1: Joint to joint scaling methods . It covered the methods ScalingStandard, ScalingUniform,
ScalingLengthMass and ScalingLengthMassFat.

This lesson introduces more scaling methods, more precisely

 ScalingUniformExt (scale equally in all directions; input is external measurements)


 ScalingLengthMassExt (scale taking mass into account; input is external measurements)
 ScalingLengthMassFatExt (scale taking mass and fat into account; input is external measurements).

Scaling External

The scaling laws we discussed in Lesson 1 are using measures for the segment lengths based on joint-to-joint distances. But some joint locations cannot be easily palpated.
The hip joints are a good example. They are located deep under the skin and are not easy to measure from the outside. So to facilitate scaling to individuals, another set of
scaling methods are provided that use only distances between external bony landmarks. The same three scaling strategies (uniform, length mass and length mass fat) are
available based on bony landmarks. They are selected like this:

// Scaling laws using joint to joint measures


//#include "..\..\..\Body\AAUHuman\Scaling\ScalingUniform.any"
//#include "..\..\..\Body\AAUHuman\Scaling\ScalingLengthMass.any"
//#include "..\..\..\Body\AAUHuman\Scaling\ScalingLengthMassFat.any"

// Scaling laws using external measures


//#include "..\..\..\Body\AAUHuman\Scaling\ScalingUniformExt.any"
//#include "..\..\..\Body\AAUHuman\Scaling\ScalingLengthMassExt.any"
#include "..\..\..\Body\AAUHuman\Scaling\ScalingLengthMassFatExt.any"
Scaling = {
//#include "..\..\..\Body\AAUHuman\Scaling\AnyFamily\AnyMan.any"
...
#include "..\..\..\Body\AAUHuman\Scaling\AnyFamily\AnyManExternal.any"
...
};

ScalingUniformExt.any, ScalingLengthMassExt.any and ScalingLengthMassFatExt.any are the scaling laws that use the external measurements. They have exactly the
same scaling properties as their corresponding joint-to-joint counterparts. And they are controlled by the file AnyManExternal.any. This last file works exactly like the
AnyMan.any file, taking as input the body mass, body height and individual segments lengths.

The external measures have to be taken at specific locations and in a specific posture as shown in the figure below. The application you have downloaded already places
the body in an appropriate posture. There is also an include file that displays the location of the different measures called DrawExternalMeasures.any. If included as shown
below it will display the exact dimensions on the model:

// Scaling laws using external measures


//#include "..\..\..\Body\AAUHuman\Scaling\ScalingUniformExt.any"
//#include "..\..\..\Body\AAUHuman\Scaling\ScalingLengthMassExt.any"
#include "..\..\..\Body\AAUHuman\Scaling\ScalingLengthMassFatExt.any"
#include "DrawExternalMeasures.any"

We should also remove the drawing of the forces on the hands to make the view clearer, it can be done by outcomenting the code in the Environment.any file:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 203 of 229

// AnyDrawVector DrawRightLoad = {
// Vec = .RightHandLoad.F*0.015;
// PointAway = On;
// GlobalCoord = On;
// Line = {
// Style = Line3DStyleFull;
// Thickness = 0.01;
// RGB = {0, 0, 0};
// End = {
// Style = Line3DCapStyleArrow;
// RGB = {0, 0, 0};
// Thickness = 0.025;
// Length = 0.025;
// };
// };
// AnyRefFrame &Hand = .RightHandLoad.Hand;
// };
//
// AnyDrawVector DrawLeftLoad = {
// Vec = .LeftHandLoad.F*0.015;
// PointAway = On;
// GlobalCoord = On;
// Line = {
// Style = Line3DStyleFull;
// Thickness = 0.01;
// RGB = {0, 0, 0};
// End = {
// Style = Line3DCapStyleArrow;
// RGB = {0, 0, 0};
// Thickness = 0.025;
// Length = 0.025;
// };
// };
// AnyRefFrame &Hand = .LeftHandLoad.Hand;
// };

After loading the model it can be observed that the red spheres on the image below show the bony landmarks used for scaling of segment lengths in these methods and the
blue lines connecting them show the actual dimensions.

Percentile scaling

While the methods described in the previous section are useful for scaling a model to a particular individual, many applications, especially within ergonomic product
design, require the model to fit an archetypical body size such as they are defined in athropometrical population statistics. So the section describes scaling of models to a
certain percentile of the population. The anthropometric data of the population are presumed to follow a Gaussian distribution and with enough measured data it is possible
to calculate the average or mean value, standard deviation and percentile values. The mean value also corresponds to the 50th percentile, meaning that 50% of the
population is larger and 50% is smaller than that exact value. Antropometric data can be found in many sources, but the files used in this section are based on this
reference: ADULTDATA, The Handbook of Adult Anthropometric Measurements. Data for Design Safety. Dept. of Trade & Industry, United Kingdom.

This scaling strategy for percentiles also uses the external measures, so you have to include one of the three external scaling laws. We shall use ScalingLengthMassFatExt,
but as you may have guessed we need a specific AnyMan file to control the percentile scaling. This one is called AnyManExtPercentile.any, it has been designed to
represent the European male population, but if you have data available for other populations it is easy to fill them in. This is how it is done (you can out comment the
DrawExternalMeasure if you don’t want it):

// Scaling laws using external measures


//#include "..\..\..\Body\AAUHuman\Scaling\ScalingUniformExt.any"
//#include "..\..\..\Body\AAUHuman\Scaling\ScalingLengthMassExt.any"
#include "..\..\..\Body\AAUHuman\Scaling\ScalingLengthMassFatExt.any"
//#include "DrawExternalMeasures.any"
Scaling = {
...

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 204 of 229

//#include "..\..\..\Body\AAUHuman\Scaling\AnyFamily\AnyManExternal.any"
#include "..\..\..\Body\AAUHuman\Scaling\AnyFamily\AnyManExtPercentile.any"
//#include "..\..\..\Body\AAUHuman\Scaling\AnyFamily\AnyWomanExtPercentile.any"
};

Open the AnyManExtPercentile file. The percentile function controls all the anthropometric data we saw previously: the body mass, body height and all segment lengths.
All you have to do is specify the Percentile variable, and due to the non linearity of the function, you also have to select the linear regression corresponding to the range of
value of the percentile.
Let’s try some example now. In the AnyManExtPercentile file give an 80th percentile as input:

// PercentileAnyVar
Percentile = 80; //Percent of the population represented. Choose one of the Z linear regression below.

You have to take care that the linear regression for Z is valid for an 80th percentile:

// Choose only one of the following linear regression depending on the percentile.
//AnyVar Z = (0.064*Percentile)-1.96; // This is an approximation valid for Percentile from 5% to 15%.
AnyVar Z = (0.0279*Percentile)-1.3971; // This is an approximation valid for Percentile from 16% to 84%.
//AnyVar Z = (0.064*Percentile)-4.44; // This is an approximation valid for Percentile from 85% to 95%.

The regression model included now is valid for Percentile from 16% to 84%. We go for 80%, so the regression is valid. You can load the model and investigate the
proportions in the model view window. 80% of the European males are smaller than the model you have now, and 20% are taller. Let’s try to model a 95th percentile male.
This time we also have to change the linear regression function:

// Percentile
AnyVar Percentile = 95; //Percent of the population represented. Choose one of the Z linear regression below.

// Choose only one of the following linear regression depending on the percentile.
//AnyVar Z = (0.064*Percentile)-1.96; // This is valid for Percentile from 5% to 15%.
//AnyVar Z = (0.0279*Percentile)-1.3971; // This is valid for Percentile from 16% to 84%.
AnyVar Z = (0.064*Percentile)-4.44; // This is valid for Percentile from 85% to 95%.

An example of application for such scaling can be a door height: we know that if the door is high enough for this model then it will be enough for 95% of the population.

As the file AnyManExtPercentile represent European male, there is a file AnyWomanExtPercentile representing European female. The percentile is specified in exactly the
same way.

You have now completed the tutorial on Scaling.

We are extremely grateful to Ford Forschungszentrum Aachen, Germany, for sponsoring the scaling implementation.

Lesson 3: Scaling based on patient-specific landmarks


This tutorial presumes that you have completed Scaling tutorial Lesson 1: Joint to joint scaling methods and Scaling tutorial Lesson 2: Scaling based on external body
measurements . They covered such methods as: ScalingStandard, ScalingUniform, ScalingLengthMass, ScalingLengthMassFat, ScalingUniformExt,
ScalingLengthMassExt, and ScalingLengthMassFatExt.

This lesson introduces an advanced scaling method based on a non-affine transformation of a set of source landmarks into a set of target points using a radial basis function
(RBF) approach.

Patient-specific scaling

Previously described scaling schemes are based on anthropometric measurements and an affine transform scaling. As such they do not reconstruct needed bone
morphology to a very high level of detail, i.e. local deformities of certain bone features may not be covered by such scaling.

The scaling law described in this lesson is based on a surface approximation which must transform (not necessary in a linear manner) a set of given points (source
landmarks) into a set of known subject-specific points (target landmarks). For this purpose the following approximation is constructed:

- where are the coefficients of the RBF functions , computed based on the source and target landmarks,

- is the polynomial of order

- is the RBF function, which can take one of the following forms:

o , – Gaussian function, or

o – Thin plate spline, or

o , – Multiquadratic function, or other.

To define such a transform in AnyScript one can use a template provided by the AnyBody Modeling System:

AnyFunTransform3DRBF <ObjectName> =

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 205 of 229

{
/*RBFDef =
{
Type = RBF_Gaussian;
Param = 1;
};*/
Points0 = ;
//RBFCoefs = ;
//PolynomDegree = -1;
//PolynomCoefs = ;
//PointDescriptions = ;
//PointNames = ;
//Points1 = ;
};

The Points0 variable is a matrix (3 x k) of the source landmark coordinates, where k is the number of source points. Points1 is the matrix of target landmarks of the same
size. These two entities alone define a 3D RBF transform.

PolynomDegree variable corresponds to the q degree of the polynomial term of the aforementioned approximation. Recommended degree is 1, i.e. a linear component of
the approximation gives good results as it was observed empirically.

RBFDef.Type defines a type of the RBF function. Possible options are RBF_Gaussian (default), RBF_ThinPlate, RBF_Biharmonic, RBF_Triharmonic,
RBF_MultiQuadratic, and RBF_InverseMultiQuadratic.

RBFDef.Param is a parameter mentioned in the definitions of various RBF functions. By varying this parameter it is possible to change the behaviour of a chosen RBF
function, e.g. prescribe a local effect of the landmarks.

PointNames is a variable to give text identifiers for the landmarks. This can be used to output to landmarks to process in external packages. Similarly, PointDescriptions is
an additional storage for more detailed information on how to locate the landmarks.

Alternative way to define an RBF transform is to specify the required approximation coefficients explicitly. This can be done by defining the RBFCoefs and PolynomCoefs
variables. However, this is a very demanding and non-intuitive procedure and preferable way is to define the corresponding sets of landmarks.

Scaling example

This section describes a step-by-step procedure how to customize your model by utilizing given subject-specific morphology. This morphology, i.e. the bone surface, could
be derived from a medical image of the subject. A number of image processing and segmentation packages, both commercial and open-source, are available to create STL
surfaces from medical images. Having obtained the target STL surface it is possible to define points on it either in any CAD package or directly in the AnyBody Modeling
System. Please note that the variables Points0 and Points1 of the AnyFunTransformRBF3D class have to be defined in the same reference frame, i.e. an initial registration
of the objects has to be done (manually or programmatically).

For this example the L5 vertebra of the lumbar spine was used as the source surface. It was extracted from the standing model of the repository by selecting an export
surface option of the corresponding AnyDrawSTL variable in the model tree view (see below):

A set of points is then selected to describe features of the vertebra, for this particular case the following anatomical features can be used:

· Transverse processes (right and left)

· Articular processes (right, left, inferior, and superior)

· Spinal process

· Vertebral body (anterior/exterior, superior/inferior, lateral)

Having found the coordinates of these landmarks, they are assigned to the Points0 variable:

Points0 =
{
{ 0.072462, 1.180805, -0.036767}, // left transverse process
{ 0.072462, 1.180805, 0.036767}, // right transverse process
{ 0.044390, 1.173952, 0.000001}, // spinal process
{ 0.063322, 1.190380, -0.022513}, // left superior articular process
{ 0.063322, 1.190380, 0.022513}, // right superior articular process
{ 0.065274, 1.155646, -0.013893}, // left inferior articular process
{ 0.065274, 1.155646, 0.013893}, // right inferior articular process
{ 0.117145, 1.179924, 0.000001}, // anterior superior point of vert. body
{ 0.107595, 1.150322, 0.000001}, // anterior inferior point of vert. body
{ 0.085754, 1.186174, 0.000001}, // posterior superior point of vert. body
{ 0.081586, 1.161476, 0.000001}, // posterior inferior point of vert. body
{ 0.099929, 1.182663, -0.023310}, // left superior lateral point of vert. body
{ 0.099929, 1.182663, 0.023310}, // right superior lateral point of vert. body
{ 0.093791, 1.158033, -0.023417}, // left inferior lateral point of vert. body
{ 0.093791, 1.158033, 0.023417} // right inferior lateral point of vert. body

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 206 of 229

};

For the demonstration purpose a random displacement field is used to simulate the subject-specific morphing scenario. Each component of the source landmark coordinates
is randomly shifted by a value in a range between -3 and 3 mm. Points1 are defined as a sum of the Points0 and the randomization matrix:

AnyMatrix randomshift =
{
{-0.003895, -0.001451, 0.001701},
{-0.008618, 0.001028, -0.002344},
{-0.001458, 0.002645, -0.002440},
{-0.002999, -0.002629, -0.001487},
{ 0.002042, -0.001206, -0.002876},
{-0.002533, 0.002108, 0.002388},
{ 0.002364, -0.001066, 0.001906},
{ 0.001912, 0.001885, -0.000878},
{ 0.002069, -0.001692, 0.001183},
{-0.002830, -0.001915, -0.002315},
{-0.002085, -0.001003, -0.002280},
{-0.001388, 0.002440, -0.002179},
{ 0.009382, 0.001788, -0.001514},
{ 0.002813, 0.002817, 0.001695},
{-0.002273, 0.002215, -0.002401}
};
Points1 = Points0 + randomshift;

Having done all of the above it is possible to use constructed scaling transform to morph the original vertebral geometry (red entities are source landmarks/surface, green
entities corresponding target landmarks and result surface):

It is important to understand that this morphing law is sensitive to the selection of landmarks, their number, polynomial order, and the parameter of the RBF function. Thus,
for a particular task it might be necessary to select and adjust the landmarks several times to achieve better fit. This morphing function is provided to facilitate non-linear
scaling, however, it does not guarantee complete match of the source and target as it is just an approximation function.

The complete model of this example can be downloaded as a zip file: ScalingRBF.zip .

Validation of models
Somewhere on the way to the decision of using a biomechanical model you have probably asked yourself the question: Will I be able to trust the results I get?

This is a very relevant question indeed. Computer models are just that: a model of reality, and there will always be some amount of approximation involved. The good
news is that with careful modeling and the 'right model for the right problem' you can get very close to reality with the AnyBody Modeling System because it is tailor-made
for the complexity of musculoskeletal systems.

Investigation of the accuracy of the model goes under the term 'validation', and this is what we will be dealing with in this tutorial. More precisely, you can expect to find
the following in this tutorial:

1. Clever ideas for validation methods.


2. Examples of models that have been validated previously.

Several previous webcasts have presented validation studies and results, the most recent one was “Seated Human Model Validation”.

What can go wrong?

Well, lots, actually. But it is helpful to try to categorize the matter into a few sources of error.

 Errors sources in the model


 Errors sources in the basic assumptions
 Errors sources in the software

Errors sources in the model

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 207 of 229

An AnyScript model contains a lot of data, and they are all infested with some degree of inaccuracy: Geometry and mass properties of segments, assumptions about the
kinematics and reactions of joints, properties and attachment points of muscles, and much more.

It has been said about biomechanics that there is a 'right' model for each case. For instance, there is little point in using a complex muscle model if you have little
information about the muscle properties, for instance fiber lengths and pennation angles. Another consideration is the level of subject-specific accuracy. Is the purpose of
the model to simulate a particular individual, or should it reflect a cross section of the population?

Model data uncertainties

In general, the models in the AnyScript Managed Model Repository are based on data reported in the literature. They often come from studies of one or few subjects or
cadavers, and the data has little or no statistical significance. You will find the references of the data listed in the comments in the individual AnyScript files. However, the
fact that a specific fiber length or muscle insertion point has been found in an individual cadaver does not mean that the value is valid for every individual or even typical.

In conclusion there is no guarantee that the values in models from any library are valid for the case you may want to analyse, and the best advice is to approach the matter
with a critical mind. If results look suspicious in some part of the model, consider whether this can be due to the model input. Some typical cases are:

 The muscle primarily responsible for carrying the load over a joint does not have sufficient strength. This can happen even in well-tested models if an unusual
loading, posture or support condition that was never tested before is imposed.
 The model has attained a posture in which the moment arm of a primary muscle erroneously becomes zero or negative. This can happen, for instance, if a wrapping
muscle slides off its wrapping surface. The variation of muscle length with the joint angle reflects the moment arm, so if the moment arm is too small, then the
muscle will have little length variation when the joint is articulated.
 If the model makes use of a muscle model with stength/length variation and passive stiffness, then a tendon length that is poorly calibrated to the model can cause
malfunction of its muscle. A too long tendon will cause its muscle to have little or no strength in its usual operation interval. A too short tendon will cause a muscle
to excert passive force and likely cause muscles on the other side of the joint to work more than they are supposed to. Please notice that AnyBody has facilities for
calibrating tendon lengths. The muscle modeling tutorial has in-depth information about these issues.

Boundary conditions

Input to inverse dynamics is movement and boundary conditions, and these can have more influence on the result than most inexperienced modelers would expect. In fact,
they are the principal source of error in many models. The human body is remarkable in its ability to make the best of the available supports, and this often creates the
illusion that supports are solid while they really are not.

Consider a hand gripping a handle firmly. Apparently, the hand is rigidly connected to the handle, and you might be inclined to define a model connection between the two
elements reflecting this notion. However, hands have limited strength to hold on with, and handle surfaces have limited friction to offer. If the model contrary to reality
offers an effortless connection between the hand and the handle, then the model is likely to exploit this as we shall see later.

Movement data

Recorded movement input such as motion capture data is usually in the form of positions over time. But inertia forces in the model are derived from accelerations, and to
obtain accelerations, the positional data must be differentiated twice thus increasing noise and inaccuracies by two orders of magnitude. This is the topic of the first lesson
of this tutorial, starting at the bottom of this page.

Errors sources in the basic assumptions

As mentioned a couple of times already, the AnyBody Modeling System is based on inverse dynamics. This means that - for a given point in time - the system solves the
equilibrium equations and resolves the interior muscle and joint forces. Since these time steps are solved independently of each other, the state can in principle shift
abruptly from one step to the next, whereas, in reality, a change of muscle tone requires a bit of time. Force development in a muscle is the result of an electric signal from
the central nervous system, which starts a chemical process in the muscle and eventually leads to contraction. All this is done within a few milliseconds, and inverse
dynamics disregards this small time delay. It means that if the movement is very quick and the system predicts very rapid changes of muscle activation, then the result may
not be realistic.

Another possible source of error is the distribution of force between the muscles. The body has more muscles than strictly necessary to carry most loads, so is infinitely
many different combinations of muscle forces will balance the external loads. The way AnyBody picks the right one is by an optimality criterion. The system presumes that
the body wants to make the best of its resources. The user has some amount of control over this criterion, but in its basic form it is a minimum fatigue criterion that
distributes the loads as evenly as possible between the muscles taking their individual strengths into account. Please refer to A Study of Studies for more detailed
information.

So the system basically presumes that the body has the knowledge and the desire to activate muscles optimally. This is supported by a lot of research, but the precise
criterion employed by the body is a matter of continuous discussion. Furthermore, the ability to instantly choose the optimal muscle recruitment most likely requires that
the movement is skilled and that the required changes of muscle activation are not faster than the electro-chemical process of muscle contraction can accommodate.

Errors in the software

All software has bugs, and very probably this is also the case for the AnyBody Modeling System. However, in terms of muscle recruitment, the validity of the software was
validated independently in 2004 in a Ph.D. thesis by Erik Forster from the University of Ulm, Germany. The thesis is available from the list of publications in the
AnyScript Forum . The basic idea was to program an independent special-purpose application for gait simulation and then compare it to an identical gait model in
AnyBody. If the results were identical, it would prove the correctness of the algorithms of both systems. The result was that the output data of the two systems were
identical on all but a tiny fraction of the data. Closer investigation of this tiny fraction revealed that different algorithms - although mathematically similar - can produce
slightly deviating results due to round-off errors.

When compared to the modeling errors and approximations due to the recruitment assumptions, errors in the software are much less likely to disturb the result of the
computation significantly.

Methods of validation

The expression 'garbage in - garbage out' is very much valid for biomechanical simulation. The quality of the output can never be better than the input. This means that the
first step of any validation is to check the quality of the input. Input comes in the form of movements and applied forces, where the former is the more difficult. A rough
check of the specified movements can be obtained by running a kinematic analysis and charting the positions, velocities and above all accelerations of characteristic points
and segments in the model as illustrated for the rowing model above. Notice that proximal body parts tend to be heavier than distal body parts, so larger accelerations are
plausible in the distal parts.

Gravity = 9.81 m/s^2 is a good measure to compare your values to. If the accelerations oscillate or attain unrealistic values, then the input positional information definitely

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 208 of 229

needs careful reviewing and probably smoothing with a low-pass filter.

Now carry on with Kinematic input validation .

Kinematic input
The picture below shows the thorax position variation over time recorded by digitizing images from a video capture (model curtesy of the Technical University of Vienna)
of ergometer rowing. The red curve is the horizontal position, and the green curve is the vertical position. The lateral position remains zero and is the blue curve. It looks
very reasonable, and it does not seem to be infested with significant noise.

To find velocities, the system automatically differentiates positional data with respect to time and we get the following:

It still looks reasonable except for a suspicion that the maximum velocity around 12 m/s may be a bit high over such a short distance. The system dfferentiates the velocity
function to obtain the accelerations, which subsequently according to the second law of Newton will generate forces:

This graph still looks nice and smooth, but notice the values: The maximum acceleration is around 300 m/s^2 or 30 g. Notice that this is for the thorax and not a distal
segment like a hand or a foot. It is not realistic, and it is in fact an artifact produced by the amplification of small errors in the positional signal through the two subsequent
differentiations.

If you work with recorded movement data, then it is very important to check that the accelerations are within reasonable limits. The movement is input in inverse
dynamics, and if the accelerations are unrealistic, then the muscle and joint forces will be too.

Too high acceerations are usually due to lack of smoothness of the recorded motion data. The solution is often to apply smoothing with a low pass filter to reduce the
unrealistic acceleratons.

Parameter studies and optimization


The AnyBody Modeling System has a nice mechanism that allows you to perform investigations of the model's reaction to its parameters and even to automatically find the
set of parameters that causes a given behavior of the model. Some examples of applications are:

 Systematic investigations of the model's sensitivity to a group of parameters such as a muscle insertion point, muscle strength, or external support point.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 209 of 229

 Posture and movement prediction.


 Optimization of muscular strength for a particular sports performance.
 Optimization of the layout of a bicycle for a particular person.
 Answering research questions such as: Could a T. rex jump? With optimization you can find the movement pattern that maximizes, for instance, the jump height
given the body weight and limitations on muscular strength.

Parameter study: Metabolic efficiency of a bicycle as a function of seat height and seat horizontal position.

This functionality is provided through two complementary studies :

The AnyParamStudy performs an exhaustive search of the variable space computing the model's reaction to every combination of the variables within a given interval.
For instance, a parameter study could investigate the metabolic efficiency of a bicycle depending on the horizontal and vertical position of the saddle. The advantage of this
study is that it gives you the ultimate overview of the system's behavior. The disadvantage is that the number of computations grows exponentially with the number of
parameters. A two-parameter problem with five values of each parameter leads to 5 x 5 = 25 analyses, which is usually no problem to do, while a five parameter problem
will lead to 5^5 = 3125 analyses, which obviously is a more time-consuming undertaking, at least for larger models.

The AnyOptStudy performs a systematic search within a parameter space using optimization techniques of solutions that fulfill certain criteria. For instance, you could ask
the study to find the saddle position that maximizes the metabolic efficiency of the bicycle while keeping the maximum muscle activity below a certain upper limit. The
advantage of this study is that it does not need to compute al combinations of the parameters and therefore can handle spaces with multiple parameters within a reasonable
time. The disadvantage is that it does not provide the overview of the design space that you get from a parameter study.

This tutorial devotes one lesson to each of the two study types:

1. Defining a parameter study


2. Optimization studies

Without further ado, let us get the parameter study defined in lesson 1 .

Defining a parameter study


A parameter study is a systematic way to vary a number of model parameters and have the system automatically run one or several analyses for each combination of
parameters.

For instance, you may want to know how the forces affecting a joint prosthesis depend on the implanted position. Or you may be interested in finding the standing posture
by which you can hold a heavy box as easily as possible between your hands. Or how the position of a handle influences the muscular effort of operating it.

Or you may be interested in knowing how the seat height and horizontal position influence the muscle effort and metabolism of the rider. This is precisely what we shall do
in this tutorial. To make life a bit easier for you, we have prepared a bicycle model you can download and play around with. Please click here to download a zip file and
unpack it to some pertinent place on your hard disk.

The bicycle model is pretty much the 2DBike that you may know from the AnyBody Managed Model Repository . In fact, the structure of the model is as in the repository,
so we have maintained the traditional division between the BRep directory containing the human body model and the ARep directory containing the bicycle. You will find
the main file, OptTutorial.main.any, in OptimBike\ARep\Aalborg\OptTutorial (Notice the file OptTutorial.final.main.any in the same location; this is a file that contains
most of the additions we make in the lessons of this tutorial). Please open The AnyBody Modeling System and load the main file. Opening a model view window should
give you this picture:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 210 of 229

As you can see the model is very simple. It has two legs and a pelvis that is rigidly fixed to the seat. The feet are attached to the crank mechanism, and the crank is loaded
by a sinusoidal torque and constant angular velocity producing a mean mechanical output of 165 W. It has a total of 18 muscles - nine on each leg. You can control the
design parameters of the bicycle and the way the rider propels the pedals by means of the variables at the top of the main file. It might be a good idea to play a bit around
with the variables and run some analyses. Try, for instance, to raise and lower the seat. Notice that if you raise the seat more than a few centimeters, the model has trouble
reaching the pedals. This is really a kinematical problem, but it causes momentarily very high muscle activities and, if you raise the seat further, makes the kinematical
analysis break down because the feet lose the contact with the pedals.

The crank torque profile of a bicycle rider changes when the set is moved horizontally because the location of the cycle's dead center changes. To account for this, a special
feature has been set up in this model to adjust the phase shift of the crank torque profile to the seat position such that the minimum crank torque occurs when the pedals
point towards the hip joint regardless of where the saddle is positioned.

Some general terminology

Before we proceed with the definition of a parameter study it might be useful to introduce the terminology used by AnyBody for parameter and optimization studies:

 A design variable is an independent parameter controlling some aspect of the model, for instance the seat height, the pedal length, the pelvic angle, the crank torque
variation, the cadence, the strength of a muscle, and so on. In short, just about any property you can set in the AnyScript model. A design variable is always a single
number and it must be associated with upper and lower variation limits, but it is allowed to construct the model such that many properties depend on each variable.
For instance, you might want to define a variable controlling the soleus muscle strength and then let the soleus muscle in both legs depend on it. In this way you can
distinguish between dependent and independent parameters, and only independent parameters can be used as design variables. The AnyScript class defining a
design variable is called AnyDesVar.
 A design measure is a dependent parameter that results from an analysis with given values of design variables. Typical examples would be the maximum muscle
activity, the metabolism, the mechanical work, the mechanical power generated by a specific muscle, or the force in a joint. The AnyScript class for definition of
design measures is the AnyDesMeasure.

These two classes are common to parameter studies and optimization studies, so the two types obviously share several concepts. Let us proceed with the definition of a
parameter study. Actually, both these studies come from the same family of classes having the AnyDesStudy as common parent; we commonly refer to these studies as
design studies. Within this kinship, they also share the definition of the "analysis" to be performed when evaluating the design measures for a certain set of design
variables. The "analysis" is in fact an AnyScript operation (AnyOperation), called Analysis, which is a member of all design studies. To state an optimization or a
parameter study properly, the design variables, the design measures, and the analysis must all be defined.

Definition of a parameter study

A parameter study is as the name indicates a study. Therefore its natural position in the model is below the existing AnyBodyStudy. We can insert a new parameter study
by means of the object inserter mechanism from the class tree. Place the cursor below the definition of the AnyBodyStudy Study, click the Classes tab in the tree view,
locate the AnyParamStudy, right-click, and insert a template of the class. You should get the following result:

AnyBodyStudy Study = {

AnyFolder &Model = .Model;

Gravity = {0.0, -9.81, 0.0};

tEnd = Main.BikeParameters.T;
};

AnyParamStudy <ObjectName> =
{
//LogFile = "";
/*Analysis =
{
//AnyOperation &<Insert name0> = <Insert object reference (or full object definition)>;
};*/
nStep = ;
AnyDesVar &<Insert name0> = <Insert object reference (or full object definition)>;
//AnyDesVar &<Insert name1> = <Insert object reference (or full object definition)>;
AnyDesMeasure &<Insert name0> = <Insert object reference (or full object definition)>;
//AnyDesMeasure &<Insert name1> = <Insert object reference (or full object definition)>;
};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 211 of 229

As you can see, this requires a bit of additional specifications and general tidying up:

AnyParamStudy ParamStudy = {
Analysis = {
//AnyOperation &<Insert name0> = <Insert object reference (or full object definition)>;
};
nStep = ;
AnyDesVar &<Insert name0> = <Insert object reference (or full object definition)>;
//AnyDesVar &<Insert name1> = <Insert object reference (or full object definition)>;
AnyDesMeasure &<Insert name0> = <Insert object reference (or full object definition)>;
//AnyDesMeasure &<Insert name1> = <Insert object reference (or full object definition)>;
};

Here's a brief explanation of the different components of a parameter study:

Parameter Function
Analysis This is a specification of the operation(s) to perform to provide the data we are studying in the parameter study. This will typically be an
InverseDynamicAnalysis operation, but it could also be simply an evaluation of some mathematical expression, or it could be a combination of multiple
operations, for instance various calibrations followed by an inverse dynamic analysis.
nStep This is a specification of how many steps to evaluate in the parameter study for each parameter.
AnyDesVar The study must declare at least one of these. It is the parameter(s) that are varied in the study and for combinations of which the model is analyzed. You
can define as many as you like, but please beware that the number of analyses in the parameter study is the product of steps for each AnyDesVar, so the
time consumption grows exponentially with the number of AnyDesVars.
AnyDesMeasure Each of these objects specifies a property that is the result of the analysis and which must be collected for further inspection as the study proceeds. You
can define as many of these as you like.

Let us insert the necessary specifications to perform a parameter study on the saddle position of the bicycle:

AnyParamStudy ParamStudy = {
Analysis = {
AnyOperation &Operation = ..Study.InverseDynamicAnalysis;
};

As you can see, this is a pointer to the inverse dynamic analysis of the existing AnyBodyStudy in the bicycle model. This specification simply means that to evaluate the
parameters we want to investigate in this parameter study, we must execute the analysis of the bicycle. This may seem obvious in a simple model like this one, but many
AnyScript models contain multiple studies and each study contains multiple operations.

The next specification deals with the parameters to vary:

nStep = ;
AnyDesVar SaddleHeight = {
Val = Main.BikeParameters.SaddleHeight;
Min = Val - 0.05;
Max = Val + 0.03;
};
AnyDesVar SaddlePos = {
Val = Main.BikeParameters.SaddlePos;
Min = Val - 0.07;
Max = Val + 0.10;
};
AnyDesMeasure &<Insert name0> = <Insert object reference (or full object definition)>;
//AnyDesMeasure &<Insert name1> = <Insert object reference (or full object definition)>;
};

Please notice here that we have removed the '&'s that were inserted in the template in front of the variable names. Instead of pointing at AnyDesVars defined elsewhere we
include the entire definition right here in the study, and this is actually the usual way to do it. Each AnyDesVar gets three properties set. The first one is called 'Val' and is
simply set equal to an existing parameter in the model. The best way to understand this statement is to think of Val as a reference variable that is equalized in the first case
with the SaddleHeight, which is a parameter defined at the top of the main file. At any time in the parameter study, Val will be equal to the saddle height as one should
expect from the assignment. But in this special case, the assignment also goes the other way: It lets the parameter study control the value of what is on the right hand side
of the equality sign, in this case the SaddleHeight parameter. We have similarly defined a second parameter, SaddlePos, which allows the parameter study to vary the
horizontal saddle position. This two-way linkage between Val and another variable in the model implies certain restrictions on what assignments AnyScript allows for this
particular case. The referred variable must be a scalar quantity, i.e. either a scalar or an element of a larger structure (e.g. vector or matrix). Secondly, it must be an
independent scalar quantity, i.e., it cannot depend (by expressions) on other variables; otherwise there would exist an ambiguity. Alternatively to linking another
independent variable in the model, Val can be initialized with constants. In this case, Val will be the only instance of the design variable and the model must depend
directly on Val. This latter use is a somewhat restricted exploitation of AnyDesVar and is typically not practical when studies of existing models are to be carried out.

The next step is to define the properties we wish to study, i.e. the dependent parameters or "design measures" of the model. As you know, after running an operation from a
study the results are available in the Output branch of the tree view of the operation and they can be plotted, dumped and copied to the clipboard and so on. Now we are
defining a study that will execute operations from other studies and assemble the results for later investigation. We might even want to make mathematical operations on
these results, combine results from different operations, and so on. To do this we must refer to the result we wish to store for further processing. There is just one semantic
problem: The results do not exist until we have performed the analysis, but we must refer to them already when we author (and load) the model.

To solve this problem we must go back to the AnyBodyStudy Study, from where we want to lift the results, and declare an object that will allow us to refer to
computational results before they are actually made. The object is of class AnyOutputFun, and we shall add it to the existing AnyBodyStudy:

// The study: Operations to be performed on the model


AnyBodyStudy Study = {

AnyFolder &Model = .Model;

Gravity = {0.0, -9.81, 0.0};

tEnd = Main.BikeParameters.T;
nStep = 50;

AnyOutputFun MaxAct = {

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 212 of 229

Val = .MaxMuscleActivity;
};

};

This allows us to refer to Study.Output.MaxMuscleActivity before it actually gets created.

AnyOutputFun is actually a class of mathematical function that returns the output (when existing) associated with the Val member. So here we have created a function
called MaxAct that takes no arguments and returns the output data for .MaxMuscleActivity. Notice that AnyOutputFun must be declared inside a study in order to resolve
the association with the output data structure of the particular study.

We can now use the output function, MaxAct, in our design measure simply by calling the function in the assignment of the Val member of the AnyDesMeasure:

AnyDesVar SaddlePos = {
Val = Main.BikeParameters.SaddlePos;
Min = Val - 0.07;
Max = Val + 0.10;
};
AnyDesMeasure MaxAct = {
Val = max(..Study.MaxAct());
};

Notice the definition. The MaxAct function for each InverseDynamicAnalysis operation returns a vector of maximum muscle activities in the model. The vector has as
many components as the study has time steps, i.e. 50 in the present case. In the definition of the AnyDesMeasure we want to save only the largest value of each of the
vector, so we wrap the call of the MaxAct function in another max function. AnyScript gives you a number of such data processing functions and we shall study others
further down. Please refer to the reference manual for further details.

One thing is missing before we can try the whole thing out: We must specify how many steps we want the parameter study to perform for each parameter. As in
AnyBodyStudies this is done by the nStep variable, but where nStep in an AnyBodyStudy is an integer variable, it is a vector with one component for each AnyDesVar in
an AnyParamStudy. We shall be modest at first and choose only five steps in each direction. And so, the final AnyParamStudy looks like this:

AnyParamStudy ParamStudy = {
Analysis = {
AnyOperation &Operation = ..Study.InverseDynamicAnalysis;
};
nStep = {5,5};
AnyDesVar SaddleHeight = {
Val = Main.BikeParameters.SaddleHeight;
Min = Val - 0.05;
Max = Val + 0.03;
};
AnyDesVar SaddlePos = {
Val = Main.BikeParameters.SaddlePos;
Min = Val - 0.07;
Max = Val + 0.10;
};
AnyDesMeasure MaxAct = {
Val = max(..Study.MaxAct());
};
};

It is finally time try it out. If you have typed everything correctly, then you should be able to load the model and expand the Operations Tree in the left hand side of the
Main Frame to this:

Make sure you have a Model View window open. Select ParameterStudy as indicated and hit the "Run" button. You should see the model starting to cycle, and if you
watch the vicinity of the saddle carefully, you will see that the hip joint is changing its position on a 5 x 5 grid. With a reasonably fast computer it should take a minute or
less to do the 25 analyses after which the computations stop. Congratulations! You have completed your first parameter study. Let us investigate the result.

The obvious way to visualize the results of a study with two parameters is as a 3-D surface. AnyBody has a window to make that type of plots. Please click Window ->
AnyChart 2D/3D (new). A new window containing a coordinate system and the usual model tree appears:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 213 of 229

The toolbar of this window indicates a kinship with the Model View window. Indeed, if you select the rotation button in the toolbar and drag the mouse with the left button
down inside the coordinate system you will notice that the system rotates just like an ordinary Model View. Now, expand the Bike2D node in the tree until you can click
the ParamStudy->Output->MaxAct->Val property. The coordinate system automatically attains a second abscissa axis and you can see a nice surface like this:

The surface shows the maximum muscle activity over the cycle for each of the 25 combinations of parameters and provides a very nice overview of the behavior of the
model. The surface reveals that the highest and most backward position is the best. Why not try higher and more backward, then? It is very simply to do:

AnyDesVar SaddleHeight = {
Val = Main.BikeParameters.SaddleHeight;
Min = Val - 0.05;
Max = Val + 0.05;
};
AnyDesVar SaddlePos = {
Val = Main.BikeParameters.SaddlePos;
Min = Val - 0.10;
Max = Val + 0.10;
};

When you re-run the parameter study, things will go well in the beginning, but towards the end of the 25 combinations you may notice muscles beginning to bulge more
and momentarily attain the color of magenta. This is the system's way of demonstrating that the muscles have been loaded above 100% of their strength. The reason why
this happens is that, as the seat rises, the model gets into positions where it is difficult for the feet to reach the pedals. Just before the feet cannot reach the pedals the knee
movements are accelerated causing large inertia forces in the system. All this happens a bit more drastically in an ideal rigid body model than it would in real life where
joints have a bit of slack, segments are slightly elastic, and the prescribed kinematics may be compromised. You can see very clearly what happens if you go back to the
AnyChart View and study the new surface:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 214 of 229

The surface is now completely dominated by the one combination, which is difficult for the model to do. You can still see the surface shape if you change the scale of the

value axis. This and all other settings are available if you click the button in the toolbar. Doing so will produce a window with a tree view in which you can select
ValueAxis->Max. Try setting Max to 0.2 and you should obtain the following:

What this study reveals is that in terms of muscle activity to drive the bicycle a high seat is advantageous, but there seems to be a very sharp limit where the leg gets close
to not being able to reach the pedals, and this should not be exceeded. One additional remark in this context is that this bicycle model has a predefined ankle angle variation
whereas a real human can compensate for a higher seat by letting the ankle operate in a more plantar-flexed position.

Before we finish this section, let us take a look at a particularly important feature of AnyScript mathematics: The ability to compute integral properties. AnyBody has a
simple way of approximating the metabolism of muscles based on the simulation of each muscle's mechanical work. Metabolism is technically a power measured in Watt,
and the sum of the individual muscle metabolisms will give us an estimate of the total metabolism involved in the bicycling process. It is fairly simple to add up the muscle
metabolisms in the AnyBody study:

// The study: Operations to be performed on the model


AnyBodyStudy Study = {

AnyFolder &Model = .Model;

RecruitmentSolver = MinMaxOOSolSimplex;
Gravity = {0.0, -9.81, 0.0};

tEnd = Main.BikeParameters.T;
nStep = 50;

// Useful variables for the optimization


AnyFolder &r = Main.Bike2D.Model.Leg2D.Right.Mus;
AnyFolder &l = Main.Bike2D.Model.Leg2D.Left.Mus;
AnyVar Pmet = r.Ham.Pmet+r.BiFemSh.Pmet+r.GlutMax.Pmet+r.RectFem.Pmet+
r.Vasti.Pmet+r.Gas.Pmet+r.Sol.Pmet+r.TibAnt.Pmet+
l.Ham.Pmet+l.BiFemSh.Pmet+l.GlutMax.Pmet+l.RectFem.Pmet+

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 215 of 229

l.Vasti.Pmet+l.Gas.Pmet+l.Sol.Pmet+l.TibAnt.Pmet;

AnyOutputFun MaxAct = {
Val = .MaxMuscleActivity;
};

};

Notice that we have defined the r and l variables for convenience to limit the size of the expressions. If you run the InverseDynamicAnalysis (go on and try!) you will find
the new variable mentioned in the list of output, and you can chart it in a ChartFX View:

The area under this curve is the total metabolism combusted over a crank revolution. To compute this we must introduce two more elements. The first one is an
AnyOutputFun as we have seen it before. The purpose if this function is to make it semantically possible to refer to the output of the Pmet variable before is has actually
been computed:

// Useful variables for the optimization


AnyFolder &r = Main.Bike2D.Model.Leg2D.Right.Mus;
AnyFolder &l = Main.Bike2D.Model.Leg2D.Left.Mus;
AnyVar Pmet = r.Ham.Pmet+r.BiFemSh.Pmet+r.GlutMax.Pmet+r.RectFem.Pmet+
r.Vasti.Pmet+r.Gas.Pmet+r.Sol.Pmet+r.TibAnt.Pmet+
l.Ham.Pmet+l.BiFemSh.Pmet+l.GlutMax.Pmet+l.RectFem.Pmet+
l.Vasti.Pmet+l.Gas.Pmet+l.Sol.Pmet+l.TibAnt.Pmet;

AnyOutputFun MaxAct = {
Val = .MaxMuscleActivity;
};
AnyOutputFun Metabolism = {
Val = .Pmet;
};

The second missing element is the actual integration of the function. This we perform in the parameter study where we define the AnyDesMeasure:

AnyParamStudy ParamStudy = {
Analysis = {
AnyOperation &op = ..Study.InverseDynamicAnalysis;
};
nStep = {10,10};
AnyDesVar SaddleHeight = {
Val = Main.BikeParameters.SaddleHeight;
Min = Val - 0.05;
Max = Val + 0.03;
};
AnyDesVar SaddlePos = {
Val = Main.BikeParameters.SaddlePos;
Min = Val - 0.07;
Max = Val + 0.10;
};

AnyDesMeasure MaxAct = {
Val = max(..Study.MaxAct());
};
AnyDesMeasure Metab = {
Val = secint(..Study.Metabolism(),..Study.tArray);
};

};

The secint function performs a numerical integration of the first argument against the second argument. Each argument must be an array and the number of components in
the two arguments must be the same.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 216 of 229

Notice the other two changes: We have changed the variable limits back to what they were before and we have decided to be a little more adventurous and have specified
10 variable steps in each direction. It is time to run the parameter study again. The new Metab variable is now available in the list under the ParamStudy in the AnyChart
window and can be plotted:

We shall return to the capabilities of the AnyChart in more detail in the next lesson , which deals with the definition of optimization studies.

Optimization studies
The parameter study introduced in the preceding lesson provides a complete overview of the design space, but the study is only feasible when the problem has few
independent parameters, preferably one or two. In the previous lesson we considered a problem with two parameters and 5 steps in each direction of the design space
leading to 5^2 = 5 x 5 = 25 analyses. If the problem had 10 parameters we would be facing 5^10 = 9.7 million analyses, which is an entirely different matter in terms of
computation times. The truth is that such so-called full factorial parameter studies are computationally infeasible when the problem has more than very few independent
parameters. So what to do?

The solution is to use a method that picks the combinations to compute carefully and only has to evaluate a few of them. One class of such methods is optimization. An
optimization algorithm systematically searches through the design space for the combination of parameters that minimizes the value of a function of the parameters, the so-
called objective function. Some algorithms also allow the definition of constraint functions, which are dependent parameters that must be maintained below a certain upper
limit.

The AnyBody Modeling System provides a study to handle optimization problems. The mathematical definition of the problem it solves is as follows:

Minimize

g 0 ( x 1 ..x n )

Subject to

g i ( x 1 ..x n ) <= 0

L j <= x j <= U j

where g 0 is called the objective function, x j , j =1.. n are the design variables, and g i , i =1.. m are the constraints. The definition of an optimization problem in AnyBody
is therefore a question of appointing independent parameters as design variables and dependent parameters as the objective function and constraints. Please notice that m
could be zero in which case we have a problem that is only constrained by the simple bounds on the variables.

In an optimization terminology, the parameter study from the preceding lesson could be defined as:

Minimize

Metabolic energy consumption

Subject to

Saddle height within predefined limits


Saddle horizontal position within predefined limits

In fact, this is precisely what we are going to do, but before we proceed, let us briefly look at the properties of a typical musculoskeletal objective function and how the
optimization algorithm solves the problem.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 217 of 229

The two pictures above both show the result of a parameter study. The picture on the right is the section indicated by the magnifying glass on the left amplified by 50 times.
As you can see, the seemingly smooth objective function has a microscopic jump. In other words the function is non-smooth and in fact discontinuous at certain points. Not
all design measures have such discontinuities, but some do. The figure also indicates that the function is smooth in between these discontinuities. Optimization algorithms
are trying to navigate on multi-dimentional hyper-surfaces with such qualities and must consequently be robust against a certain amount of non-smoothness. The
optimization algorithm in AnyBody is indeed capable of doing this in most cases. It is a special version of a so-called feasible directions algorithm, which seeks out the
optimum in two-step loops. The two steps are:

1. Decide on a search direction.


2. Perform a linear search to find the minimum along the chosen direction.

This means that it is only necessary to perform analyses of the function values at the points that the algorithm actually visits and not all points in a predefined grid as we
did in the parameter study. It also means that the algorithm depends on the smoothness of the surface when it decides on a direction to take in step 1, but once the direction
has been chosen, the line search in step 2 can be done with methods that do not predispose smoothness.

Now that we know what to expect, we can proceed to the actual definition of the optimization study. The previous definition of the parameter study will help us a lot
because an optimization study has almost exactly the same structure. So the first step would be to simply copy the parameter study:

AnyParamStudy ParamStudy = {
Analysis = {
AnyOperation &Operation = ..Study.InverseDynamicAnalysis;
};
nStep = {5,5};
AnyDesVar SaddleHeight = {
Val = Main.BikeParameters.SaddleHeight;
Min = Val - 0.05;
Max = Val + 0.03;
};
AnyDesVar SaddlePos = {
Val = Main.BikeParameters.SaddlePos;
Min = Val - 0.07;
Max = Val + 0.10;
};
AnyDesMeasure MaxAct = {
Val = max(..Study.MaxAct());
};
};

AnyParamStudy ParamStudy = {
Analysis = {
AnyOperation &Operation = ..Study.InverseDynamicAnalysis;
};
nStep = {5,5};
AnyDesVar SaddleHeight = {
Val = Main.BikeParameters.SaddleHeight;
Min = Val - 0.05;
Max = Val + 0.03;
};
AnyDesVar SaddlePos = {
Val = Main.BikeParameters.SaddlePos;
Min = Val - 0.07;
Max = Val + 0.10;
};
AnyDesMeasure MaxAct = {
Val = max(..Study.MaxAct());
};
AnyDesMeasure Metab = {
Val = secint(..Study.Metabolism(),..Study.tArray);
};
};

We proceed to change a few parameters:

AnyOptStudy OptStudy = {
Analysis = {
AnyOperation &Operation = ..Study.InverseDynamicAnalysis;
};
AnyDesVar SaddleHeight = {
Val = Main.BikeParameters.SaddleHeight;
Min = Val - 0.05;
Max = Val + 0.03;
};
AnyDesVar SaddlePos = {
Val = Main.BikeParameters.SaddlePos;
Min = Val - 0.07;
Max = Val + 0.10;
};
AnyDesMeasure Metab = {
Val = secint(..Study.Metabolism(),..Study.tArray);
Type = ObjectiveFun;
};
};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 218 of 229

Please notice that the AnyDesMeasure MaxAct was removed, and so was the entire line with the nStep specification. The optimization study does not use any particular
step size but rather adapts its steps automatically to find the accurate position of the optimum. This is another advantage of optimization over a parameter study. Finally, we
have added a type specification to the Metab object specifying that this is the objective function of the problem.

This is the definition of an optimization problem that will vary the saddle height and horizontal position to minimize the metabolism. Let us run it and see what happens.
Load the model in and please make sure that you have a Model View window open so that you can see the difference in the way the seat position is varied compared to the
parameter study.

If the model loads you should get a screen picture similar to the one above this text. Expand the OptStudy branch in the operations tree, click Optimization once and then
the Run button. The model starts cycling and after a few rounds you will notice the saddle position changing, but not in a systematic grid like in the parameters study. What
you will see is gradual changes back and forth in different directions until the changes wear off and the position converges. Every time you see the step counter below the
Run button changing number it is an indication that the optimizer has picked a new optimization direction to try. You should see the number increasing in slow steps up to
six before the process stops and the system announces that it is finished. Please notice that the changes of saddle position in the last several steps is very minute, which is
typical for optimization: the first steps bring large changes and large improvements, while the last many steps only improve slightly.

Now we are going to study the results in more detail using the AnyChart window. Do you still have the AnyChart window from the previous lesson with the Metabolism
parameter study open? It should look like this:

If not, please run the ParamStudy again and plot the surface. When you have this surface ready, please open another AnyChart window by clicking Window->AnyChart
2D/3D (new). In the new window, please expand the tree down to Main.Bike2D.OptStudy.Output.Metab. Then click the Val variable under Metab. This produces a simple
2-D graph showing the development of the metabolism over the 5 iterations:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 219 of 229

The graph confirms that the vast majority of the improvement is obtained in a couple of iterations and the final iteration contributes only by a minor, almost
insignificant adjustment. Such iterations with insignificant improvements occur due to the convergence criterion, i.e., the criterion that stops the optimization process. The
optimizer does not detect mathemtically that the objective function has an optimum value; it merely detects that the changes of the found solution are small from one
iteration to the next. Therefore, the optimization process will always end with one (or more) steps with insignificant changes.

The optimal solution in the Model View looks like this:

Just above the Metab variable in the tree you can find the two independent variables, SaddleHeight and SaddlePos, and they can be graphed the same way revealing that
their convergence is less monotone over the iterations. This is also quite usual for optimization processes.

An interesting way to investigate the convergence is to plot it in the variable/objective space rather than over the iterations. This is what we need the window with the
parameter study surface for. At the top of this window you will find panels listing series and data to be plotted. Please right-click in the series window and select "New":

This will give you a blank "Series 1". When you highlight it by clicking with the mouse you will see the list of Selected Objects in the right-hand pane is empty. We are
going to fill in the SaddleHeight and SaddlePos variables from the OptStudy as Abscissa and Abscissa2, respectively. This is done by selecting Abscissa and Abscissa2 in
turn and then expanding the OptStudy branch until the SaddleHeight.Val and SaddlePos.Val, respectively, can be selected:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 220 of 229

Finally, in the Value field select OptStudy.Metab.Val and look carefully at the plot. You will see that an additional polyline has been added. It originates approximately at
the middle of the surface and shows the path the optimization process has taken through the design space to the minimum point. You can change the color of the line by
clicking the leftmost button (Properties) in the toolbar directly over the graphics pane. This gives you access to all the settings and lets you control the appearance of graphs
in detail. In the picture below we have selected RGB = {0,0,1}, i.e. blue, for Series1 and Thickness = 2:

This plot illustrates the convergence history in the "landscape" of the objective function. Here we can see the reasons for the convergence being as it is. Actually, the
optimum value lies in a relatively flat region and therefore the exact mathematical location of the optimum may be of a more academic importance than practical
relevance since we can find many design point with almost the same objective function value.

"A flat optimum", like this, can occasionally cause problems for the optimization process to provide exact convergence because it is difficult to distinguish between
insignificant changes due to flatness or convergence. Furthermore, one more obstacle for finding the exact optimum is present in the given case. The objective function is
not as smooth as the parameter study with the relative crude grid indicates. Below you see the result of a parameter study, we have prepared for a small 2 by 2 mm design
area in the vicinity of the end-point of the fist optimization step.

This reveals a somewhat jagged surface and a distinct (local) valley of the objective function. Minor changes of the input to the optimization process, whether it be the
starting point or design variable bounds, can actually make the optimization process dive into this local valley and get stuck in there.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 221 of 229

An optimization process that gets stuck in this local minimum could have a convergence history like in the plots shown below

Notice how the final objective function value is slightly higher than the previous optimization result. Notice also how only the first iteration out of 7 provides significant
improvement of the objective function. This step brings the design value down into to the valley. The remaining iterations zigzags in the bottom of the valley without being
able to get up and out and without providing any visible improvement. Finally, the convergence criterion is fulfilled. It can be mentioned that the convergence criterion
requires both objective and design changes to be small.

In the beginning of this lesson, we mentioned that the optimization problem formulation also handles constraints. They can be used for all sorts of purposes. For instance
we notice that the optimal solution is a rather low saddle position, cf. the picture above. Suppose that for some reason, this position is too low. We, therefore, want to
ensure that the distance between the crank and the seat is not too small, for instance larger than 0.66 m. This can be formulated very nicely as a constraint like this:

AnyDesMeasure Metab = {
Val = secint(..Study.Metabolism(),..Study.tArray);
Type = ObjectiveFun;
};
AnyDesMeasure SeatDist = {
Val = (.SaddleHeight.Val^2+.SaddlePos.Val^2)^0.5 - 0.66;
Type = GreaterThanZero;
};

Notice that constraints are defined as AnyDesMeasures of type LessThanZero or GreaterThanZero. In the mathematical formulation of the optimization problem stated in
the beginning of this lesson, we have only less-than-or-equal-to constraints, but there is only a minus sign in difference of making a greater-than-or-equal-to into a less-
than-or-equal-to constraint. You can put this minus sign manually or you can use Type = GreaterThanZero, which is equivalent. Notice that equality constraints are in
principle also a possibility, but currently the optimization solvers in AnyBody do not handle this type of constraints. Moreover, it is most often possible to handle equality
constraints by means of inequality constraints, because the objective function's gradient will put pressure on the constraint from one side; thus, it is merely a matter of
determining the proper type of inequality constraint.

Notice also that the constraint is just an AnyDesMeasure, so anything you could conceivably use as an objective function can also be a constraint. In this case, the
constraint is a simple mathematical combination of variables, but in general it can also be properties such as muscle forces, joint reactions, point locations, segment
velocities, and any other model property that the system can compute.

Enough talk; let's try the optimization with the constraint added. Please load the model again, select the optimization operation, and click the run button. The optimization
process will have the following convergence picture:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 222 of 229

If you alo re-run the parameter study, you can get this picture of the convergence:

We see that the result is indeed a compromise since the objective function value cannot be reduced as much as in the unconstrained case. The path of the design
values bounces off the constraint and finally it gets stuck on the constraint even though the objective function still has a downwards inclination. The constraint lies like a
wall through the design space. We can see the convergence path along the constraint by plot the constraint value, i.e., the SeatDist.Val. This looks like:

where it is obvious how the optimizer hits the constraint, bounces off, hits again, etc. and finally it converges. At no point in time, the constraint value becomes negative,
which was exactly what we prescribed in its definition.

A final look at the result could be the picture of the model after this constained optimization, which shows a visible difference compared to the unconstrained solution: The
hip position is now higher, i.e., longer from the crank and to achieve this it is further forward, see the picture below:

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 223 of 229

This completes the introduction to optimization studies.

Optimization studies can be used for many purposes. A previous webcast on “How to synthesize posture and movement with inverse dynamics” is available for download
and replay here .

Posture and movement prediction


Just about every example you find in these tutorials is based on the concept of inverse dynamics, which in some sence is the opposite of forward dynamics. To understand
the difference between these two concepts it is useful to have a brief look at Newton's second law. It states the following:

F=ma

where F is the vector of resulting forces acting on a body with mass m causing an acceleration vector, a . So, if we know the acceleration, i.e. the movement of the system,
then we can find the forces acting on it. That is inverse dynamics, and this is why AnyBody usually requires us to specify the movement or posture of the model before it
can compute anything for us.

But we can also re-arrange the equation to this form:

a = F /m

In this version, if we know the forces, we can determine the movement. This is called forward dynamics. The problem with forward dynamics is that input to the analysis
will be some information about the muscle forces and this is usually hard to determine experimentally and even more difficult to guess.

But what if we know neither the movement nor the muscle forces? In that case we have two unknowns and only one equation and it seems like our venture into
musculoskeletal analysis is destined to failure no matter what we do. This tutorial shows how the optimization capability in AnyBody can help you solve that kind of
problems. They technically go under the name "Posture and Motion Prediction" and the idea is that rather than inputting a known posture or movement we want the model
to predict how a human body is likely going to move in a given situation. Since this involves optimization and optimization takes time we are going to formulate a very
simple problem, but the principle applies to much more complex models as well.

Understanding this tutorial requires a-priory knowledge of the tutorial on Parameter Studies and Optimization .

Definition of the problem

As the name indicates, in posture and movement optimization we use optimization to compensate for the fact the do not know the movement a-priori. So, instead of feeding
the movement to the analysis we have to feed something into an optimization problem, and that something has to be the ultimate goal of the movement.

For some movements this goal is quite obvious. The objective of a high jump, for instance, is to jump as high as possible, so we could simply ask the optimizer to
determine the movement pattern that leads to the highest possible jump. Of course it would not be allowed to have movements that require more muscle strength than the
body has available, so we would also have to formulate a constraint ensuring that the maximum muscle activation stays below 100%.

For other movements the goal is less clear. If we want to predict the movement of lifting a coffee cup from the table to the mouth then what would a reasonable goal be?
The constraints are rather easy: Start at the table, end at the mouth, keep the cup horizontal all the time, avoid accelerations that would spill the coffee and so on, but many
different movements would honor those conditions. Which of them would be the one a given person would actually choose? Some investigations indicate that for
submaximal tasks like this, a lazyness criterion often applies; we try to get around the task as effortlessly as possible in some sense. But we really do not know. In this case,
the user could try different objectives and decide on one that leads to a plausible movement.

A football kick

So we need a simple model to play with. We are going to try to optimize a two-dimensional football kick. There are all sorts of reasons why a simple model of this task
might be totally inadequate, but it will serve well to demonstrate the idea. Please download a model to begin on. Right-click the link and save the file in some working
directory. Then open it up in the AnyBody Modeling System, load it in and open a ModelView window to have a look at the model. You should see something like this
(except the legends):

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 224 of 229

It is a two-segment model with revolute joints at the hip and the knee, so it has in total two degrees of freedom. Let us imagine that no motion capture experiment has been
performed, so we do not really know how the model will kick. But we have made the initial guess that both of the two joints are moving with constant velocity just to have
some movement to look at. Please select the InverseDynamicAnalysis operation and run it. You will be rewarded with a very fast analysis but should be able to see that the
leg performs a kick.

The system also gives you the following warning:

MyStudy : The muscles in the model are not loaded due to kinetically over-constrained mechanical system.

MyStudy.InverseDynamics : No muscles in the model. 49) ...Inverse dynamic analysis completed

We get this message because the model has no muscles and the necessary joint torques to produce the movement are provided by the drivers. We are going to want the
model to relate to realistic joint strengths as opposed to the infinitely strong driver reaction moments. On the other hand we want to keep it simple. So rather than defining a
lof of muscles representing the real anatomy of the leg we shall just add "joint muscles" to the hip and knee joints representing realistic strengths. We are going to need
such joint muscles for flexion and extension respectively for both of the two joints. The red lines below add such muscles with realistic joint strengths in Newton-meter.
For an explanation of the use of the AnyGeneralMuscle class, please refer to the muscle modeling tutorial .

AnyKinEqSimpleDriver KneeDriver = {
DriverPos = {-90*pi/180};
DriverVel = {90*pi/180}/..MyStudy.tEnd;
AnyRevoluteJoint &Joint = .Knee;
};

// Hip joint muscles


AnyGeneralMuscle HipFlex = {
AnyMuscleModel Model = {F0 = 232;};
ForceDirection = 1;
AnyRevoluteJoint &Joint = .Hip;
};
AnyGeneralMuscle HipExtend = {
AnyMuscleModel Model = {F0 = 251;};
ForceDirection = -1;
AnyRevoluteJoint &Joint = .Hip;
};

// Knee joint muscles


AnyGeneralMuscle KneeExtend = {
AnyMuscleModel Model = {F0 = 554;};
ForceDirection = 1;
AnyRevoluteJoint &Joint = .Knee;
};
AnyGeneralMuscle KneeFlex = {
AnyMuscleModel Model = {F0 = 236;};
ForceDirection = -1;
AnyRevoluteJoint &Joint = .Knee;
};

Please copy and paste the red lines into your model just below the KneeDriver definition as indicated. Then remove the reaction moments from the drivers like this:

AnyKinEqSimpleDriver HipDriver = {
DriverPos = {-90*pi/180};
DriverVel = {90*pi/180}/..MyStudy.tEnd;
Reaction.Type = {Off};
AnyRevoluteJoint &Joint = .Hip;
};
AnyKinEqSimpleDriver KneeDriver = {
DriverPos = {-90*pi/180};
DriverVel = {90*pi/180}/..MyStudy.tEnd;
Reaction.Type = {Off};
AnyRevoluteJoint &Joint = .Knee;

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 225 of 229

};

After you reload and re-run the model you should be able to open a ChartFX window, plot the MaxMuscleActivity and get this:

The movement we have imposed is unrealistic. Both joints move with constant angular velocity while, in a realistic case, the model should capture the fact that it is
necessary to accelerate the leg from some start position to the velocity it has at impact. To obtain a realistic and "designable" movement we have to replace the two simple
drivers on the hip and knee with something more general. The interpolation driver is excellent for this purpose because it allows us to determine the position of each joint
in certain time steps through the kick and subsequently will interpolate between those loctions to generate a smooth motion.

// AnyKinEqSimpleDriver HipDriver = {
// DriverPos = {-90*pi/180};
// DriverVel = {90*pi/180}/..MyStudy.tEnd;
// Reaction.Type = {Off};
// AnyRevoluteJoint &Joint = .Hip;
// };
//
// AnyKinEqSimpleDriver KneeDriver = {
// DriverPos = {-90*pi/180};
// DriverVel = {90*pi/180}/..MyStudy.tEnd;
// Reaction.Type = {Off};
// AnyRevoluteJoint &Joint = .Knee;
// };

// Some initial guesses for the hip and knee angle


// movements.
AnyKinEqInterPolDriver HipDriver = {
T = {0, 0.25, 0.50, 0.75, 1}*..MyStudy.tEnd;
Data = {{-30, -30, -15, 0, 30}}*pi/180;
Type = Bspline;
BsplineOrder = 4;
AnyRevoluteJoint &Joint = .Hip;
Reaction.Type = {Off};
};

AnyKinEqInterPolDriver KneeDriver = {
T = {0, 0.25, 0.50, 0.75, 1}*..MyStudy.tEnd;
Data = {{-70, -70, -50, -40, -30}}*pi/180;
Type = Bspline;
BsplineOrder = 4;
AnyRevoluteJoint &Joint = .Knee;
Reaction.Type = {Off};
};

A fast reload and run of the model will show that the movement is somewhat different now, and plotting the joint rotation velocities will also show that the initial velocity
is now zero for both joints. This is ensured by using similar values for the first two points in each interpolation, for instance -30 and -30 degrees in the HipDriver. Now we
could generate infinitely many different motions simply by inserting different angle values into these interpolation drivers. Among them will be the motion that generates
the fastest kick without overloading the muscles. Unfortunately infinity is a very high numbr and we could never finish searching for our solution and this is where the
optimizer can help us. We ask the optimizer to determine the best movement by making these variations.

The optimization problem

We already have some data now that can be used in the definition of our optimization problem. The first question is: What do we actually want to optimize? Given that the
mass of the foot and football are given in advance we can presume that maximising the velocity of the football after the impact is equivalent to maximizing the velocity of
the foot before the impact. In fact, the law of conservation of momentum says something about that. If we presume the mass of the football to be 0.2 kg, the coefficient of
restitution of the collision to be 0.5, which is typical for a football kick, and presume that the ball is at rest before impact then we have enough information to predict the
velocity of the ball after the impact given the velocity of the foot before the impact. We can write this formula directly into the model like this:

// The study: Operations to be performed on the model


AnyBodyStudy MyStudy = {
AnyFolder &Model = .MyModel;
RecruitmentSolver = MinMaxSimplex;
Gravity = {0.0, -9.81, 0.0};
nStep = 50;
tEnd = 0.2;
AnyOutputFun BallVel= {
Val = 1.5*Main.MyModel.Shank.Mass*Main.MyModel.Shank.rDot[0]/(0.2+Main.MyModel.Shank.Mass);
};
};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 226 of 229

Please load and run the model again, and then go to the ChartFX window and plot the new output function. You should see this:

The function shows the predicted post-impact velocity of the ball if the foot were to hit is at any time during the imposed movement. As expected, the exit velocity is
higher the later in the movement the ball is hit because the foot velocity increases all the time.

We also want to be able to limit the muscle activation to prevent overloading of the muscles, and we make a similar function for that purpose:

// The study: Operations to be performed on the model


AnyBodyStudy MyStudy = {
AnyFolder &Model = .MyModel;
RecruitmentSolver = MinMaxSimplex;
Gravity = {0.0, -9.81, 0.0};
nStep = 50;
tEnd = 0.2;
AnyOutputFun BallVel= {
Val = 1.5*Main.MyModel.Shank.Mass*Main.MyModel.Shank.rDot[0]/(0.2+Main.MyModel.Shank.Mass);
};
AnyOutputFun MaxAct = {
Val = .MaxMuscleActivity;
};
};

With that we should be ready to define an optimization problem. A basic optimization study would look like this:

// Optimize the ball velocity after the kick.


AnyOptStudy OptStudy = {
LogFile = "OptStudy.log";
MaxIterationStep = 25;

Analysis = {
AnyOperation &op = ..MyStudy.InverseDynamicAnalysis;
};

// Constraint: All muscle activities below 100%


AnyDesMeasure MaxActivity = {
Val = max(..MyStudy.MaxAct()-1);
Type = LessThanZero;
};

// Objective function: Max horizontal velocity of the foot


AnyDesMeasure KickVel = {
Val = -max(..MyStudy.BallVel());
Type = ObjectiveFun;
};
};

Please copy and paste those lines into the model right after the end of MyStudy but before the final ending brace of the model. The study contains two AnyDesMeasures of
which the first is the maximum activity minus one. The actual constraint is

max(Activity) < 100%

but, because AnyBody requires zero right hand sides for all its constraints, it is defined on the form

max(Activity) - 1< 0

The second AnyDesMeasure, KickVel, is defined as minus the maximum of the ball velocity. This is because AnyBody's optimizer is set up to always perform
minimization where we want to maximize the velocity. So we simply minimize the negative velocity instead. The max value is derived first, presuming that the kicker will
decide to hit the ball at the optimal time in the kick.

Loading the model at this time will produce an error message because we have not defined any design variables yet. Let us begin with a single variable just to make sure
we get it right before adding a lot of them:

// Objective function: Max horizontal velocity of the foot


AnyDesMeasure KickVel = {
Val = -max(..MyStudy.BallVel());
Type = ObjectiveFun;
};

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 227 of 229

AnyVar slack = 60*pi/180;


AnyDesVar Knee4 = {
Val = Main.MyModel.KneeDriver.Data[0][3];
Min = Val - .slack;
Max = Val + .slack;
};

This design variable controls the position of the fourth data point (remember that items in arrays are numbered from zero, so number three is the fourth position) in the
knee joint driver. There are five point in total in each driver, but we do not want to include the last one in the optimization because it determines the position of the foot at
the end of the analysis and we want this to be on the ball.

The variable names "slack" determines the upper and lower bound of the variations of joint angle position. We have placed this in a variable because it makes it easy to
change the bounds simultaneously for all design variables later.

If you reload the model now you can actually already do an optimization with the single variable. Open the OptStudy branch of the tree on the left hand side of the screen,
highlight "Optimization", and click "Run. After a few moments the process will converge to a better kick. You can see how much better by going to the ChartFX view,
openeing the OptStudy section and plotting "Main.OptStudy.Output.KickVel.Val". You will see that the optimization decreased the value from about -9 to about -12,
indicating an improvement of the ball velocity from 9 to 12 m/s.

Let us quickly add some more variables:

AnyVar slack = 60*pi/180;


AnyDesVar Hip3 = {
Val = Main.MyModel.HipDriver.Data[0][2];
Min = -30*pi/180;
Max = Val + .slack;
};
AnyDesVar Hip4 = {
Val = Main.MyModel.HipDriver.Data[0][3];
Min = Val - .slack;
Max = Val + .slack;
};
AnyDesVar Knee3 = {
Val = Main.MyModel.KneeDriver.Data[0][2];
Min = Val - .slack;
Max = Val + .slack;
};
AnyDesVar Knee4 = {
Val = Main.MyModel.KneeDriver.Data[0][3];
Min = Val - .slack;
Max = Val + .slack;
};

Notice how we have only added design variables for points 3 and 4 in each joint angle interpolation. This is because we want to retain the beginning and ending positions
and we want to make sure the velocity in the beginning remains zero, which is accomplished by keeping the second point the same as the first point.

Running the optimization at this stage will make the problem converge in a few interations to an optimized ball velocity of a little over 13 m/s. If we plot the two joint
accelerations we get:

The movement shows subtle signs of a whiplash action in the sense that the movement is initiated by a knee acceleration, which is taken over by the hip acceleration, after
which the peak knee acceleration sets in after the hip acceleration has topped. However, more whiplash effect could be expected and the final ball velocity of 13 m/s is not
very impressive for a football kick.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 228 of 229

In other words, the movement is not entirely satisfactory. This could likely be because the optimizer does not have enough freedom to control the movement, and this can
possibly be improved by adding additional points to the interpolation and making them variables in the optimization problem. Optimization problems are often ongoing
projects in the sense that is it difficult to know when the model is good enough to capture the features of the body's function that we are looking for.

Trouble shooting AnyScript models


If you think mechanics is simple, it's probably just because you haven't worked with three-dimensional space yet. The laws of mechanics are pretty easy to comprehend as
long as stuff is moving on a one-dimensional line. When you go to two dimensions, complications such as rotational inertia and centrifugal forces start to play a role, but
the equations are still not very difficult. The third dimension is what complicates things enormously and even to the point that mere kinematics becomes a matter for
university scholars. It is quite literally rocket science.

A system like AnyBody is a tremendous help in this situation because it sets up and handles all the equations inside the system and relieves you of the task of actually
handling the mathematics. But the system does not prevent you from creating models where the syntax or semantics of the model is invalid, where segments cannot reach
their joints, where the kinematics is undefined, or where there are not enough muscles to balance the forces in the system. You are likely to run into all these problems.

More precisely, you can get the following types of errors:

 Load-time errors - when the AnyScript model is syntactically erroneous


 Run-time errors - when a successfully loaded model refuses to be analyzed.

Load-time errors

A load-time error occurs when you load a model by pressing F7 or the M<-S icon on top of each window. This causes the system to attempt a compilation of the model you
have in the window, and any errors occurring in this respect are load-time errors.

Load-time errors are problems with the syntax of the AnyScript model you have authored. Such a model must honor a number of very formal semantic rules to be valid,
and if it fails the test of any of those, you will get a load-time error.

Each possible error that can occur is associated with an error message, and the system will print the message in the message window at the bottom of the screen, for
instance like this:

ERROR : C:\MyDocuments\AnyScripts\Main.any(42) : AnyVar : unexpected

or like this:

ERROR : C:\MyDocuments\AnyScripts\Main.any(45) : cannot open file : DrawSetting.any

or this:

ERROR : C:\MyDocuments\AnyScripts\Main.any(133) : EOF : unexpected

As you can see, error messages adhere to a certain structure. The first part after ERROR is the file in which the system encountered the error. Notice that this may be a
different file from the one you were loading because the main file may spawn to include files during the loading of the model.

After the file name you find a number in parenthesis. This is the number of the line where the error occurred. If you double-click the file name or the number, the file
opens, and the cursor is placed at the line in question. Be sure to click the file name or line number and not the error message.

After the line number comes the actual specification of the error. With good descriptive error messages and easy access to the error location you should have the problem
fixed in no time. Unfortunately things are not always that nice. First of all, the error messages are not always very descriptive. This is a problem the AnyBody Modeling
System shares with any other computer language compiler in the market. It is not because programmers specifically want to bother their users. The problem is simply that
error messages are generated by a very formal semantic analysis. This makes them very different from the natural human expression of the problem, and they can be
difficult for the user to understand. But you can get used to them and people have been known to even grow fond of their conciseness.

The second and more serious problem is that the error may occur in a totally different location from where it really is. Let's take an example: Suppose by mistake you have
included the wrong file like this:

#include "TheWrongFile.any"

somewhere in the model. When the compiler spawns to the wrong file it is likely to meet statements or references to objects that do not exist. The compiler will report en
error in WrongFile.any, but the real error is in the file that included WrongFile.any.

Here are some typical errors and their consequences:

Every statement in AnyScript must be terminated by a semicolon, and it is easy to forget. The consequence is that the compiler will proceed to the
next line and probably report that it has encountered something unexpected there. By closer investigation, the next line may be fully in order, and you
Forgotten
get confused. The problem was really on the former line.
semicolon
Notice also that end braces must also have a semicolon after them.
Braces {} are used to group things together in AnyScript. They must be coherent and balanced, and if you have one too few or one too many it can
completely change the structure of the code, and you can get strange error messages. The best remedy is to use consistent indentations in the code.
Unbalanced This makes it easy to follow the brace level and spot mistakes.
braces
The AnyScript editor can indent your code automatically. If you select all the text and press Alt-F8, all lines are indented according to the brace level,
and this often makes it much easier to see where the problem is. Beware that the missing brace can be in an include file.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011
AnyBody™ Tutorials Page 229 of 229

Mix-up of
Some nationalities use decimal commas, and some use decimal points. The AnyBody Modeling System consistently uses decimal points regardless of
decimal points
the nationality settings in your computer. If you type a comma in place of a decimal point, you will get a syntax error.
and commas
Mix-up of 'O' and
Beware that there is a difference between the letter 'O' and the digit zero, '0'.
'0'
Mix-up of 'l' and
Beware that there is a difference between the letter 'l' and the digit one, '1'.
'1'
AnyScript is case-sensitive, so these two statements refer to different variables:

MyVariable = 1;
Inconsistent use Myvariable = 1;
of capitals

This also means that predefined class names such as AnyVar or AnyFolder must be written with correct capitalization.
If by mistake you assign two folders to each other:

AnyFolder MyFolderCopy = MyFolder;

you will get the error message:

Missing reference Folder assignment expected for this object.


operator
What the message means is that this type of assignment is not allowed. You may argue that the error message is misleading because '=' is indeed an
assignment operator. However, operators in AnyScript are polymorphic, and they are interpreted in the context of the variables they operate on, and
for two folders no proper assignment operator exists. So, while rhetorically correct, what the statement really means is that you are missing an
ampersand, '&'. Assignment of folders to each other must be by reference like this.

AnyFolder &MyFolderCopy = MyFolder;

Some classes in AnyScript have members that must be initialized. For instance, this declaration

AnySeg arm = {
Mass = 12;
};

will produce the error:

Obligatory initialization of member : AnyVec3 Jii is missing.

Missing expected The reason is that AnySeg has a property called Jii which must be given a value before the definition is complete. Similarly, some objects have
members properties that are untouchable. This declaration:

AnySeg arm = {
t = 12;
};

also causes an error:

t : Initialization denied.

because t is a protected variable. It is set automatically by the system and cannot be assigned a value by the user.

Run-time errors

Run-time errors occur during analysis of a successfully loaded model. Their nature and remedies are completely dependent on the nature of the study. Please refer to the
tutorial " A study of studies " for further information.

file://C:\Users\Matthew\AppData\Local\Temp\~hhAD5A.htm 8/29/2011

You might also like