9 Muscle Wrapping and Via Points

9.1 Via Points

Multipoint springs and muscles are implemented by the classes MultiPointSpring and MultiPointMuscle, respectively. The relationship between MultiPointSpring and MultiPointMuscle is the same as that between AxialSpring and Muscle: The latter is a subclass of the former, and allows the creation of active tension forces in response to its excitation property.

An application allocates one of these components, sets the appropriate material properties for the tension forces, and then adds points and wrappable objects as desired.

Points can be added, queried, and removed using the methods

   void addPoint (Point pnt)
   Point getPoint (int idx)
   int numPoints()
   boolean removePoint (Point pnt)

As with AxialSpring, there must be at least two points anchoring the beginning and end of the spring. Any additional points will be via points.

Figure 9.5: A multipoint spring with two segments, separated by a blue via point (top), with the rightmost segment set to be wrappable so that it can wrap around a cylinder. The right image shows the wrappable segment’s knots.

The section of a multipoint spring between any two adjacent points is known as a segment. By default, each segment forms a straight line between the two points and does not interact with any wrappable obstacles. To interact with wrappables, a segment needs to be declared wrappable, as described in Section 9.2.

Spring construction is illustrated by the following code fragment:

   MultiPoint spring = new MultiPointSpring();
   spring.setMaterial (new LinearAxialMaterial (stiffness, damping));
   spring.addPoint (p0); // start point
   spring.addPoint (p1); // via point
   spring.addPoint (p2); // via point
   spring.addPoint (p3); // stop point

This creates a new MultiPointSpring and sets its material to a simple linear material with a specified stiffness and damping. Four points p0, p1, p2, p3 are then added, forming a start point, two via points, and a stop point.

9.1.1 Example: a muscle with via points

Figure 9.6: ViaPointMuscle model loaded into ArtiSynth.

A simple example of a muscle containing via points is given by artisynth.demos.tutorial.ViaPointMuscle. It consists of a MultiPointMuscle passing through two via points attached to a block. The code is given below:

1 package artisynth.demos.tutorial;
2
3 import java.awt.Color;
4
5 import artisynth.core.gui.ControlPanel;
6 import artisynth.core.materials.SimpleAxialMuscle;
7 import artisynth.core.mechmodels.FrameMarker;
8 import artisynth.core.mechmodels.MechModel;
9 import artisynth.core.mechmodels.MultiPointMuscle;
10 import artisynth.core.mechmodels.Particle;
11 import artisynth.core.mechmodels.RigidBody;
12 import artisynth.core.workspace.RootModel;
13 import maspack.matrix.Point3d;
14 import maspack.render.RenderProps;
15
16 public class ViaPointMuscle extends RootModel {
17
18    protected static double size = 1.0;
19
20    public void build (String[] args) {
21       MechModel mech = new MechModel ("mech");
22       addModel (mech);
23
24       mech.setFrameDamping (1.0); // set damping parameters
25       mech.setRotaryDamping (0.1);
26
27       // create block to which muscle will be attached
28       RigidBody block = RigidBody.createBox (
29          "block", /*widths=*/1.0, 1.0, 1.0, /*density=*/1.0);
30       mech.addRigidBody (block);
31
32       // create muscle start and end points
33       Particle p0 = new Particle (/*mass=*/0.1, /*x,y,z=*/-3.0, 0, 0.5);
34       p0.setDynamic (false);
35       mech.addParticle (p0);
36       Particle p1 = new Particle (/*mass=*/0.1, /*x,y,z=*/3.0, 0, 0.5);
37       p1.setDynamic (false);
38       mech.addParticle (p1);
39
40       // create markers to serve as via points
41       FrameMarker via0 = new FrameMarker();
42       mech.addFrameMarker (via0, block, new Point3d (-0.5, 0, 0.5));
43       FrameMarker via1 = new FrameMarker();
44       mech.addFrameMarker (via1, block, new Point3d (0.5, 0, 0.5));
45
46       // create muscle, set material, and add points
47       MultiPointMuscle muscle = new MultiPointMuscle ();
48       muscle.setMaterial (new SimpleAxialMuscle (/*k=*/1, /*d=*/0, /*maxf=*/10));
49       muscle.addPoint (p0);
50       muscle.addPoint (via0);
51       muscle.addPoint (via1);
52       muscle.addPoint (p1);
53       mech.addMultiPointSpring (muscle);
54
55       // set render properties
56       RenderProps.setSphericalPoints (mech, 0.1, Color.WHITE);
57       RenderProps.setCylindricalLines (mech, 0.03, Color.RED);
58
59       createControlPanel();
60    }
61
62    private void createControlPanel() {
63       // creates a panel to adjust the muscle excitation
64       ControlPanel panel = new ControlPanel ("options", "");
65       panel.addWidget (this, "models/mech/multiPointSprings/0:excitation");
66       addControlPanel (panel);
67    }
68 }

Lines 21-30 of the build() method create a MechModel and add a simple rigid body block to it. Two non-dynamic points (p0 and p1) are then created to act as muscle end points (lines 33-38), along with two markers (via0 and via1) which are attached to the block to act as via points (lines 41-44). The muscle itself is created by lines 42-53, with the end points and via points being added in order from start to end. The muscle material is a SimpleAxialMuscle, which computes tension according to the simple linear formula (4.1) described in Section 4.5.1. Lines 56-57 set render properties for the model, and line 59 creates a control panel (Section 5.1) that allows the muscle excitation property to be interactively controlled.

To run this example in ArtiSynth, select All demos > tutorial > ViaPointMuscle from the Models menu. The model should load and initially appear as in Figure 9.6. Running the model will cause the block to fall and swing about under gravity, while changing the muscle’s excitation in the control panel will vary its tension.