You are viewing the documentation for OpenSim 3.x. 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)); // Add the muscle controller to the model osimModel.addController(muscleController);
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);
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.
// Define contact geometry // Create new floor contact halfspace ContactHalfSpace *floor = new ContactHalfSpace(SimTK::Vec3(0), SimTK::Vec3(0, 0, -0.5*SimTK_PI), ground, "floor"); // Create new cube contact mesh OpenSim::ContactMesh *cube = new OpenSim::ContactMesh("blockRemesh192.obj", SimTK::Vec3(0), SimTK::Vec3(0), *block, "cube"); // Add contact geometry to the model osimModel.addContactGeometry(floor); osimModel.addContactGeometry(cube); // Contact parameters double stiffness = 1.0e7, dissipation = 0.1, friction = 0.2, viscosity=0.01; // Define contact parameters for elastic foundation force OpenSim::ElasticFoundationForce::ContactParameters *contactParams = new OpenSim::ElasticFoundationForce::ContactParameters(stiffness, dissipation, friction, friction, viscosity); contactParams->addGeometry("cube"); contactParams->addGeometry("floor"); // Create a new elastic foundation (contact) force between the floor and cube. OpenSim::ElasticFoundationForce *contactForce = new OpenSim::ElasticFoundationForce(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.