3 Mechanical Models I

3.1 Points, particles, and springs

One of the most basic types of mechanical model consists simply of springs acting on points or particles.

3.1.1 Points

Points and particles are both instances of the class Point, and are dynamic components containing a three-dimensional position state and a corresponding velocity state. Subclasses of Point include Particle (discussed below), as well as markers (such as FrameMarker and FemMarker), which are massless point markers that can be attached to rigid bodies and FE models. The position and velocity state can be accessed by the following methods:

Point3d getPosition()

Returns the point’s position.

void setPosition (Point3d pos)

Sets the point’s position.

Vector3d getVelocity()

Returns the point’s velocity.

void setVelocity (Vector3d vel)

Sets the point’s velocity.

Points also maintain forces, which cause them and/or other dynamic components in the system to move. Force accessors include:

Vector3d getForce()

Returns the net force on the point.

Vector3d addForce(Vector3d f)

Adds f to the point’s net force.

Vector3d getExternalForce()

Returns the external force acting on the point.

void setExternalForce (Vector3d f)

Sets the external force acting on the point to f.

External forces are forces explicitly set by the application; once set, they will remain the same until setExternalForce() is called again. Net forces are the sum of the external forces plus all other forces arising from gravity, damping, springs, FE elements, etc. Net forces are zeroed and recomputed at the start of each simulation step. Applications (and custom defined force effectors in particular) can add to the net force using addForce().

3.1.2 Particles

Particles, implemented by Particle, are points that contain mass and hence can move and respond to forces independently. A subclass of Particle is FemNode3d, which describes the nodes of an FE model (Chapter 6).

Several constructors are available to create particles, including

Particle (double mass)

Create a particle with specified mass.

Particle (double mass, Point3d pos)

Create a particle at a specified position.

Particle (double mass, double x, double y, double z)

Create a particle at a specified position.

Particle (String name, double mass, double x, double y, double z)

Create a named particle.

Once created, a particle should be added to the MechModel. The standard way is to add it to the model’s particles container, as illustrated by the following code fragment:

import artisynth.core.mechmodels.Particle;
import maspack.matrix.Point3d;
...
   MechModel mech;
   ...
   double mass = 0.1;
   Particle p = new Particle (mass, new Point3d (2.0, 0.0, 1.0));
   mech.addParticle (p);

The particles container can be managed by the following MechModel methods:

void addParticle (Particle p)

Adds particle p to the container.

boolean removeParticle (Particle p)

Removes particle p from the container.

void clearParticles()

Removes all particles.

PointList<Particle> particles()

Returns the particles container.

If desired, applications can also place particles in custom containers (Section 4.8).

3.1.3 Axial springs and materials

An axial spring is a simple spring that connects two points and is implemented by the class AxialSpring. This is a force effector component that exerts equal and opposite forces on the two points, along the line separating them, with a magnitude f that is a function f(l,\dot{l}) of the distance l between the points, and the distance derivative \dot{l}.

Axial springs connect only two points, but the more complex MultiPointSpring described in Chapter 9 can be used for more complex paths that contain via points and obstacle wrapping.

Each axial spring is associated with an axial material, implemented by a subclass of AxialMaterial, that specifies the function f(l,\dot{l}). The most basic type of axial material is a LinearAxialMaterial, which determines f according to the linear relationship

f(l,\dot{l})=k(l-l_{0})+d\dot{l} (3.0)

where l_{0} is the rest length and k and d are the stiffness and damping terms. Both k and d are properties of the material, while l_{0} is a property of the spring.

Axial springs are assigned a linear axial material by default. More complex, nonlinear axial materials may be defined in the package artisynth.core.materials. Setting or querying a spring’s material may be done with the methods setMaterial() and getMaterial().

3.1.4 Axial spring components

Constructors that create an AxialSpring include:

AxialSpring (double k, double d, double l0)

Create a spring with a linear material.

AxialSpring (String name, double k, double d, double l0)

Create a named spring with a linear material.

AxialSpring (String name, double l0)

Create a named spring with specified rest length.

AxialSpring (String name)

Create a named spring.

All of these create springs with linear axial material, with the parameters k, d, and l0 specifying stiffness, damping, and rest length. If not specified, these have default value of 1, 0 and 0.

If a different axial material is needed (Section 3.1.7), the following methods can be used to query and set the material:

AxialMaterial getMaterial()

Returns the current material.

void setMaterial (AxialMaterial mat)

Sets the current material.

Once created, an axial spring must be connected to its points and added to the MechModel. The following methods can be used to connect the points:

void setPoints (Point p0, Point p1)

Attaches the spring to points p0 and p1.

void setPoints (Point p0, Point p1, double l0)

Attaches p0 and p1 and sets the rest length.

The standard way to add a spring to the MechModel is to use the model’s axialSprings container, which is managed using the following MechModel methods:

void addAxialSpring (AxialSpring spr)

Adds spring spr to the container.

boolean removeAxialSpring (AxialSpring spr)

Removes spring spr from the container.

void clearAxialSprings()

Removes all springs.

RenderableComponentList<AxialSpring> axialSprings()

Returns the axialSprings container.

If desired, applications can also place springs in custom containers (Section 4.8).

MechModel also supplies a convenience method to both connect the points and add the spring to the model (the points themselves must still be added separately):

void attachAxialSpring (Point p0, Point p1, AxialSpring spr)

Attaches spr to p0 and p1 and adds it to the model.

3.1.5 Example: a simple particle-spring model

Figure 3.1: ParticleSpring model loaded into ArtiSynth.

A complete application model that implements a simple particle-spring model is given below.

1 package artisynth.demos.tutorial;
2
3 import java.awt.Color;
4 import maspack.matrix.*;
5 import maspack.render.*;
6 import artisynth.core.mechmodels.*;
7 import artisynth.core.materials.*;
8 import artisynth.core.workspace.RootModel;
9
10 /**
11  * Demo of two particles connected by a spring
12  */
13 public class ParticleSpring extends RootModel {
14
15    public void build (String[] args) {
16
17       // create MechModel and add to RootModel
18       MechModel mech = new MechModel ("mech");
19       addModel (mech);
20
21       // create the components
22       Particle p1 = new Particle ("p1", /*mass=*/2, /*x,y,z=*/0, 0, 0);
23       Particle p2 = new Particle ("p2", /*mass=*/2, /*x,y,z=*/1, 0, 0);
24       AxialSpring spring = new AxialSpring ("spr", /*restLength=*/0);
25       spring.setPoints (p1, p2);
26       spring.setMaterial (
27          new LinearAxialMaterial (/*stiffness=*/20, /*damping=*/10));
28
29       // add components to the mech model
30       mech.addParticle (p1);
31       mech.addParticle (p2);
32       mech.addAxialSpring (spring);
33
34       p1.setDynamic (false);                // first particle set to be fixed
35
36       // increase model bounding box for the viewer
37       mech.setBounds (/*min=*/-1, 0, -1, /*max=*/1, 0, 0);
38       // set render properties for the components
39       RenderProps.setSphericalPoints (p1, 0.06, Color.RED);
40       RenderProps.setSphericalPoints (p2, 0.06, Color.RED);
41       RenderProps.setCylindricalLines (spring, 0.02, Color.BLUE);
42    }
43 }

Line 1 of the source defines the package in which the model class will reside, in this case artisynth.demos.tutorial. Lines 3-8 import definitions for other classes that will be used.

The model application class is named ParticleSpring and declared to extend RootModel (line 13), and the build() method definition begins at line 15. (A no-args constructor is also needed, but because no other constructors are defined, the compiler creates one automatically.)

To begin, the build() method creates a MechModel named "mech", and then adds it to the models list of the root model using the addModel() method (lines 18-19). Next, two particles, p1 and p2, are created, with masses equal to 2 and initial positions at 0, 0, 0, and 1, 0, 0, respectively (lines 22-23). Then an axial spring is created, with end points set to p1 and p2, and assigned a linear material with a stiffness and damping of 20 and 10 (lines 24-27). Finally, after the particles and the spring are created, they are added to the particles and axialSprings lists of the MechModel using the methods addParticle() and addAxialSpring() (lines 30-32).

At this point in the code, both particles are defined to be dynamically controlled, so that running the simulation would cause both to fall under the MechModel’s default gravity acceleration of (0,0,-9.8). However, for this example, we want the first particle to remain fixed in place, so we set it to be non-dynamic (line 34), meaning that the physical simulation will not update its position in response to forces (Section 1.2.4).

The remaining calls control aspects of how the model is graphically rendered. setBounds() (line 37) increases the model’s “bounding box” so that by default it will occupy a larger part of the viewer frustum. The convenience method RenderProps.setSphericalPoints() is used to set points p1 and p2 to render as solid red spheres with a radius of 0.06, while RenderProps.setCylindricalLines() is used to set spring to render as a solid blue cylinder with a radius of 0.02. More details about setting render properties are given in Section 4.3.

To run this example in ArtiSynth, select All demos > tutorial > ParticleSpring from the Models menu. The model should load and initially appear as in Figure 3.1. Running the model (Section 1.5.3) will cause the second particle to fall and swing about under gravity.

3.1.6 Damping parameters

Mechanical models usually contain damping forces in addition to spring-type restorative forces. Damping generates forces that reduce dynamic component velocities, and is usually the major source of energy dissipation in the model. Damping forces can be generated by the spring components themselves, as described above.

A general damping can be set for all particles by setting the MechModel’s pointDamping property. This causes a force

{\bf f}_{i}=-d_{p}{\bf v}_{i} (3.0)

to be applied to all particles, where d_{p} is the value of the pointDamping and {\bf v}_{i} is the particle’s velocity.

pointDamping can be set and queried using the MechModel methods

  setPointDamping (double d);
  double getPointDamping();

In general, whenever a component has a property propX, that property can be set and queried in code using methods of the form

  setPropX (T d);
  T getPropX();

where T is the type associated with the property.

pointDamping can also be set for particles individually. This property is inherited (Section 1.4.3), so that if not set explicitly, it inherits the nearest explicitly set value in an ancestor component.

3.1.7 Axial materials

As indicated above, different materials can be supplied to an axial spring in addition to the default linear material. Most of these are related to modeling muscles, tendons and ligaments and are presented in detail in Section 4.5.

Application authors may also create their own custom axial materials by subclassing AxialMaterial and overriding the functions

double computeF (double l, double ldot, double l0, double excitation)

Computes tension f.

double computeDFdl (double l, double ldot, double l0, double excitation)

Computes \partial f/\partial l.

double computeDFdldot (double l, double ldot, double l0, double excitation)

Computes \partial f/\partial\dot{l}.

boolean isDFdldotZero()

Returns true if \partial f/\partial\dot{l}\equiv 0.

where l and l0 are the muscle length and rest length, ldot is \dot{l}, and excitation is an additional excitation signal a, which is usually in the range [0,1] and is used to implement active springs and in particular is used to implement the muscle materials of Section 4.5.

The first three methods should return the values of

f(l,\dot{l},a),\quad\frac{\partial f(l,\dot{l},a)}{\partial l},\quad\text{and}%
\quad\frac{\partial f(l,\dot{l},a)}{\partial\dot{l}}, (3.0)

respectively, while the last method should return true if \partial f(l,\dot{l},a)/\partial\dot{l}\equiv 0; i.e., it is always 0.