You are viewing the documentation for OpenSim 2.4. Are you looking for the latest OpenSim 4.0 Documentation?

Performing a Simulation Part Three

The steps covered in part three are:

Add Two Opposing Muscles

To prevent the block from falling through the ground, we create two opposing muscles between the ground and block. Note that this must be done before the call to initSystem, or else the muscles are not included in the simulation.

// Create two new muscles with the these parameters
double maxIsometricForce = 1000.0, optimalFiberLength = 0.1, tendonSlackLength = 0.2, pennationAngle = 0.0, 
activation = 0.0001, deactivation = 1.0;
 
// Create new muscle 1 using the Shutte 1993 muscle model
// Note: activation/deactivation parameters are set differently between the models.
Thelen2003Muscle *muscle1 = new 
Thelen2003Muscle("muscle1", maxIsometricForce,
optimalFiberLength, tendonSlackLength, pennationAngle);
muscle1->setActivationTimeConstant(activation);
muscle1->setDeactivationTimeConstant(deactivation);
 
// Create new muscle 2 using the Thelen 2003 muscle model
Thelen2003Muscle *muscle2 = new 
Thelen2003Muscle("muscle2", maxIsometricForce,
optimalFiberLength, tendonSlackLength, pennationAngle);
muscle2->setActivationTimeConstant(activation);
muscle2->setDeactivationTimeConstant(deactivation); 
 
// Specify the paths for the two muscles
// Path for muscle 1
muscle1->addNewPathPoint("muscle1-point1", ground, Vec3(0.0,0.05,-0.35));
muscle1->addNewPathPoint("muscle1-point2", *block, Vec3(0.0,0.0,-0.05));
 
// Path for muscle 2
muscle2->addNewPathPoint("muscle2-point1", ground, Vec3(0.0,0.05,0.35));
muscle2->addNewPathPoint("muscle2-point2", *block, Vec3(0.0,0.0,0.05)); 
 
// Add the two muscles (as forces) to the model
osimModel.addForce(muscle1);
osimModel.addForce(muscle2); 

Prescribe Muscle Controls from Functions

We define the control values for each muscle as a linear function of time defined by the slope of the line and its intercept (value when time=0). We define two linear function one for each muscle in the tug-of-war.

// Create a prescribed controller that simply applies controls as function of time
PrescribedController *muscleController = new PrescribedController();
muscleController->setActuators(osimModel.updActuators());
  
// Define linear functions for the control values for the two muscles
Array<double> slopeAndIntercept1(0.0, 2); // array of 2 doubles
Array<double> slopeAndIntercept2(0.0, 2);
 
// muscle1 control has slope of -1 starting 1 at t = 0
slopeAndIntercept1[0] = -1.0/(finalTime-initialTime); slopeAndIntercept1[1] = 1.0;
 
// muscle2 control has slope of 1 starting 0.05 at t = 0
slopeAndIntercept2[0] = 1.0/(finalTime-initialTime); slopeAndIntercept2[1] = 0.05; 
 
// Set the indiviudal muscle control functions for the prescribed muscle controller
muscleController->prescribeControlForActuator("muscle1", new LinearFunction(slopeAndIntercept1));
muscleController->prescribeControlForActuator("muscle2", new
LinearFunction(slopeAndIntercept2)); 

Define the Initial Activation and Fiber Length States

In addition, we define the initial activation and fiber length of each muscle. Once these parameters are set, we initialize the states for each muscle.

 

// Define the initial states for the two muscles
// Initial activation correspond to control at time=0
muscle1->setDefaultActivation(slopeAndIntercept1[1]);
muscle2->setDefaultActivation(slopeAndIntercept2[1]);

// Fiber length
muscle2->setDefaultFiberLength(0.1);
muscle1->setDefaultFiberLength(0.1);
 
// Compute initial conditions for muscles
osimModel.computeEquilibriumForAuxiliaryStates(si);

 

 

Exercise 5: After we compile and run the current main program, we can load the motion in the OpenSim GUI (same file name tugOfWar_states_degrees.mot as before) and visualize the simulation.

Figure: Simulation of a falling block suspended by muscles

Except for the colors, you should see something like the above in the GUI. Using the motion slider and video controls, visualize the motion. You should see the block falling under gravity but then restrained by the muscles. Then, you should see the block respond to the controls.

Add Contact Geometry and Elastic Foundation Force

As you have seen, display geometry does not cause contact forces. To prevent the block from penetrating the floor, we create some contact geometry and an elastic foundation force between the floor and a cube.

// Create new contact geometry for the floor and a cube
// Create new floor contact halfspace
ContactHalfSpace *floor = new ContactHalfSpace(SimTK::Vec3(0), SimTK::Vec3(0, 0, -0.5*SimTK::Pi), ground);
floor->setName("floor");
 
// Create new cube contact mesh
OpenSim::ContactMesh *cube = new OpenSim::ContactMesh("blockRemesh192.obj", SimTK::Vec3(0), SimTK::Vec3(0), *block); 
cube->setName("cube"); 
 
// Add contact geometry to the model
osimModel.addContactGeometry(floor);
osimModel.addContactGeometry(cube); 
 
// Create a new elastic foundation force between the floor and cube.
OpenSim::ElasticFoundationForce *contactForce = new OpenSim::ElasticFoundationForce();
OpenSim::ElasticFoundationForce::ContactParameters contactParams;
contactParams.updGeometry().append("cube");
contactParams.updGeometry().append("floor");
contactParams.setStiffness(1.0e8);
contactParams.setDissipation(0.01);
contactParams.setDynamicFriction(0.25);
contactForce->updContactParametersSet(). append(contactParams);
contactForce->setName("contactForce"); 
 
// Add the new elastic foundation force to the model
osimModel.addForce(contactForce);

Exercise 6: The complete program up to this point can be found in the file TugOfWar6_AddContact.cpp. You can use CMake to generate a new solution file with this as the TARGET, or manually replace the previous source file with this one, from within Visual Studio. Make sure the file blockRemesh192.obj is in your working directory.

After we compile and run the current main program, we can load the motion in the OpenSim GUI (same file name tugOfWar_states_degrees.mot as before) and visualize the simulation.


Figure: Muscle actuated block gliding on a contact surface

Except for the colors, you should see something like the above in the GUI. Using the motion slider and video controls, visualize the motion. You should see that the block no longer falls through the floor but settles there and then responds to the controls.

OpenSim is supported by the Mobilize Center , an NIH Biomedical Technology Resource Center (grant P41 EB027060); the Restore Center , an NIH-funded Medical Rehabilitation Research Resource Network Center (grant P2C HD101913); and the Wu Tsai Human Performance Alliance through the Joe and Clara Tsai Foundation. See the People page for a list of the many people who have contributed to the OpenSim project over the years. ©2010-2024 OpenSim. All rights reserved.