One of the most basic types of mechanical model consists simply of springs acting on points or particles.
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().
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:
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).
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
that
is a function
of the distance
between the points,
and the distance derivative
.
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
. The most basic type of axial material is
a LinearAxialMaterial, which
determines
according to the linear relationship
| (3.0) |
where
is the rest length and
and
are the stiffness and
damping terms. Both
and
are properties of the material, while
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().
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
,
and
.
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. |
A complete application model that implements a simple particle-spring model is given below.
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
. 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.
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
| (3.0) |
to be applied to all particles, where
is the value of the pointDamping and
is the particle’s velocity.
pointDamping can be set and queried using the MechModel methods
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.
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 |
| double computeDFdl (double l, double ldot, double l0, double excitation) |
Computes |
| double computeDFdldot (double l, double ldot, double l0, double excitation) |
Computes |
| boolean isDFdldotZero() |
Returns true if |
where l and l0 are the muscle length and rest length, ldot is
, and excitation is an additional excitation signal
,
which is usually in the range
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
| (3.0) |
respectively, while the last method should return true if
; i.e., it is
always 0.