/** * main routine to run the model. */ int main() { try { // Create an OpenSim model and set its name Model luxo; luxo.setName("LuxoMuscle"); // This method takes an empty model and fills it with a working // Luxo Jr. lamp skeleton! createLuxoJr(luxo); std::cout << "Finished making Luxo Jr skeleton" << std::endl; // Turn on 3D visualization for this Luxo lamp model luxo.setUseVisualizer(true); luxo.updDisplayHints().set_show_frames(true); // Pose the model State& state = luxo.initSystem(); std::cout << "State initialized." << std::endl; // Configure the 3D visualizer environment luxo.updMatterSubsystem().setShowDefaultGeometry(false); Visualizer& viz = luxo.updVisualizer().updSimbodyVisualizer(); viz.setBackgroundType(viz.GroundAndSky); viz.setShowSimTime(true); SimTK::Transform camera_pose( camera_offset_distance*camera_offset_direction); camera_pose.updR().setRotationFromOneAxis( camera_offset_direction.negate(), ZAxis); //viz.setCameraTransform(camera_pose); //viz.pointCameraAt(camera_look_at, Vec3(0,1,0)); // show the model! viz.report(state); // Create the force reporter for obtaining the forces applied to the // model during a forward simulation ForceReporter* reporter = new ForceReporter(&luxo); luxo.addAnalysis(reporter); //setup simulation // Create the integrator for integrating system dynamics SimTK::RungeKuttaMersonIntegrator integrator(luxo.getMultibodySystem()); integrator.setAccuracy(1.0e-6); // Create the manager managing the forward integration and its outputs Manager manager(luxo, integrator); // Print out details of the model luxo.printDetailedInfo(state, std::cout); // Integrate from initial time to final time manager.setInitialTime(0.0); manager.setFinalTime(sim_time); std::cout<<"Integrating for " << sim_time << " seconds" <<std::endl; manager.integrate(state); std::cout<<"Integration finished."<<std::endl; ////////////////////////////// // SAVE THE RESULTS TO FILE // ////////////////////////////// // Save the model luxo.print("Luxo_Myo.osim"); // Save the model states from forward integration auto statesTable = manager.getStatesTable(); STOFileAdapter::write(statesTable, "luxo_states.sto"); // Save the forces auto forcesTable = reporter->getForcesTable(); STOFileAdapter::write(forcesTable, "luxo_forces.sto"); std::cout << "OpenSim example completed successfully.\n"; // enter anything in the command prompt to quit std::cout << "Enter anything to quit." << std::endl; std::cin.get(); } catch (OpenSim::Exception ex) { std::cout << ex.getMessage() << std::endl; return 1; } catch (std::exception ex) { std::cout << ex.what() << std::endl; return 1; } catch (...) { std::cout << "UNRECOGNIZED EXCEPTION" << std::endl; return 1; } return 0; }
/** * Run a simulation of a sliding block being pulled by two muscle */ int main() { std::clock_t startTime = std::clock(); try { /////////////////////////////////////////////// // DEFINE THE SIMULATION START AND END TIMES // /////////////////////////////////////////////// // Define the initial and final simulation times double initialTime = 0.0; double finalTime = 10.0; /////////////////////////////////////////// // DEFINE BODIES AND JOINTS OF THE MODEL // /////////////////////////////////////////// // Create an OpenSim model and set its name Model osimModel; osimModel.setName("tugOfWar"); // GROUND FRAME // Get a reference to the model's ground body Ground& ground = osimModel.updGround(); // Add display geometry to the ground to visualize in the GUI ground.attachGeometry(new Mesh("ground.vtp")); ground.attachGeometry(new Mesh("anchor1.vtp")); ground.attachGeometry(new Mesh("anchor2.vtp")); // BLOCK BODY // Specify properties of a 20 kg, 10cm length block body double blockMass = 20.0, blockSideLength = 0.1; Vec3 blockMassCenter(0); Inertia blockInertia = blockMass*Inertia::brick(blockSideLength, blockSideLength, blockSideLength); // Create a new block body with the specified properties OpenSim::Body *block = new OpenSim::Body("block", blockMass, blockMassCenter, blockInertia); // Add display geometry to the block to visualize in the GUI block->attachGeometry(new Mesh("block.vtp")); // FREE JOINT // Create a new free joint with 6 degrees-of-freedom (coordinates) // between the block and ground bodies double halfLength = blockSideLength/2.0; Vec3 locationInParent(0, halfLength, 0), orientationInParent(0); Vec3 locationInBody(0, halfLength, 0), orientationInBody(0); FreeJoint *blockToGround = new FreeJoint("blockToGround", ground, locationInParent, orientationInParent, *block, locationInBody, orientationInBody); // Set the angle and position ranges for the free (6-degree-of-freedom) // joint between the block and ground frames. double angleRange[2] = {-SimTK::Pi/2, SimTK::Pi/2}; double positionRange[2] = {-1, 1}; blockToGround->updCoordinate(FreeJoint::Coord::Rotation1X).setRange(angleRange); blockToGround->updCoordinate(FreeJoint::Coord::Rotation2Y).setRange(angleRange); blockToGround->updCoordinate(FreeJoint::Coord::Rotation3Z).setRange(angleRange); blockToGround->updCoordinate(FreeJoint::Coord::TranslationX).setRange(positionRange); blockToGround->updCoordinate(FreeJoint::Coord::TranslationY).setRange(positionRange); blockToGround->updCoordinate(FreeJoint::Coord::TranslationZ).setRange(positionRange); // Add the block body to the model osimModel.addBody(block); osimModel.addJoint(blockToGround); /////////////////////////////////////// // DEFINE FORCES ACTING ON THE MODEL // /////////////////////////////////////// // MUSCLE FORCES // Create two new muscles double maxIsometricForce = 1000.0, optimalFiberLength = 0.2, tendonSlackLength = 0.1, pennationAngle = 0.0, fatigueFactor = 0.30, recoveryFactor = 0.20; // fatigable muscle (Millard2012EquilibriumMuscle with fatigue) FatigableMuscle* fatigable = new FatigableMuscle("fatigable", maxIsometricForce, optimalFiberLength, tendonSlackLength, pennationAngle, fatigueFactor, recoveryFactor); // original muscle model (muscle without fatigue) Millard2012EquilibriumMuscle* original = new Millard2012EquilibriumMuscle("original", maxIsometricForce, optimalFiberLength, tendonSlackLength, pennationAngle); // Define the path of the muscles fatigable->addNewPathPoint("fatigable-point1", ground, Vec3(0.0, halfLength, -0.35)); fatigable->addNewPathPoint("fatigable-point2", *block, Vec3(0.0, halfLength, -halfLength)); original->addNewPathPoint("original-point1", ground, Vec3(0.0, halfLength, 0.35)); original->addNewPathPoint("original-point2", *block, Vec3(0.0, halfLength, halfLength)); // Define the default states for the two muscles // Activation fatigable->setDefaultActivation(0.01); original->setDefaultActivation(0.01); // Fiber length fatigable->setDefaultFiberLength(optimalFiberLength); original->setDefaultFiberLength(optimalFiberLength); // Add the two muscles (as forces) to the model osimModel.addForce(fatigable); osimModel.addForce(original); /////////////////////////////////// // DEFINE CONTROLS FOR THE MODEL // /////////////////////////////////// // Create a prescribed controller that simply supplies controls as // a function of time. // For muscles, controls are normalized stoor-neuron excitations PrescribedController *muscleController = new PrescribedController(); muscleController->setActuators(osimModel.updActuators()); // Set the prescribed muscle controller to use the same muscle control function for each muscle muscleController->prescribeControlForActuator("fatigable", new Constant(1.0)); muscleController->prescribeControlForActuator("original", new Constant(1.0)); // Add the muscle controller to the model osimModel.addController(muscleController); // Add a Muscle analysis MuscleAnalysis* muscAnalysis = new MuscleAnalysis(&osimModel); Array<std::string> coords(blockToGround->getCoordinate(FreeJoint::Coord::TranslationZ).getName(),1); muscAnalysis->setCoordinates(coords); muscAnalysis->setComputeMoments(false); osimModel.addAnalysis(muscAnalysis); // Turn on the visualizer to view the simulation run live. osimModel.setUseVisualizer(false); ////////////////////////// // PERFORM A SIMULATION // ////////////////////////// // Initialize the system and get the state SimTK::State& si = osimModel.initSystem(); // Init coords to 0 and lock the rotational degrees of freedom so the block doesn't twist CoordinateSet& coordinates = osimModel.updCoordinateSet(); coordinates[0].setValue(si, 0); coordinates[1].setValue(si, 0); coordinates[2].setValue(si, 0); coordinates[3].setValue(si, 0); coordinates[4].setValue(si, 0); coordinates[5].setValue(si, 0); coordinates[0].setLocked(si, true); coordinates[1].setLocked(si, true); coordinates[2].setLocked(si, true); // Last coordinate (index 5) is the Z translation of the block coordinates[4].setLocked(si, true); // Compute initial conditions for muscles osimModel.equilibrateMuscles(si); // Create the integrator, force reporter, and manager for the simulation. // Create the integrator SimTK::RungeKuttaMersonIntegrator integrator(osimModel.getMultibodySystem()); integrator.setAccuracy(1.0e-6); // Create the force reporter ForceReporter* reporter = new ForceReporter(&osimModel); osimModel.updAnalysisSet().adoptAndAppend(reporter); // Create the manager Manager manager(osimModel, integrator); // Print out details of the model osimModel.printDetailedInfo(si, std::cout); // Integrate from initial time to final time manager.setInitialTime(initialTime); manager.setFinalTime(finalTime); std::cout<<"\nIntegrating from "<<initialTime<<" to "<<finalTime<<std::endl; manager.integrate(si); ////////////////////////////// // SAVE THE RESULTS TO FILE // ////////////////////////////// // Save the simulation results // Save the states auto statesTable = manager.getStatesTable(); STOFileAdapter_<double>::write(statesTable, "tugOfWar_fatigue_states.sto"); auto forcesTable = reporter->getForcesTable(); STOFileAdapter_<double>::write(forcesTable, "tugOfWar_fatigue_forces.sto"); // Save the muscle analysis results IO::makeDir("MuscleAnalysisResults"); muscAnalysis->printResults("fatigue", "MuscleAnalysisResults"); // Save the OpenSim model to a file osimModel.print("tugOfWar_fatigue_model.osim"); } catch (const std::exception& ex) { std::cout << ex.what() << std::endl; return 1; } catch (...) { std::cout << "UNRECOGNIZED EXCEPTION" << std::endl; return 1; } std::cout << "main() routine time = " << 1.e3*(std::clock()-startTime)/CLOCKS_PER_SEC << "ms\n"; std::cout << "OpenSim example completed successfully.\n"; return 0; }
/** * Run a simulation of block sliding with contact on by two muscles sliding with contact */ int main() { try { // Create a new OpenSim model Model osimModel; osimModel.setName("osimModel"); osimModel.setAuthors("Matt DeMers"); double Pi = SimTK::Pi; // Get the ground body Ground& ground = osimModel.updGround(); ground.attachGeometry(new Mesh("checkered_floor.vtp")); // create linkage body double linkageMass = 0.001, linkageLength = 0.5, linkageDiameter = 0.06; Vec3 linkageMassCenter(0,linkageLength/2,0); Inertia linkageInertia = Inertia::cylinderAlongY(linkageDiameter/2.0, linkageLength/2.0); OpenSim::Body* linkage1 = new OpenSim::Body("linkage1", linkageMass, linkageMassCenter, linkageMass*linkageInertia); linkage1->attachGeometry(new Sphere(0.1)); // Graphical representation Cylinder cyl(linkageDiameter/2, linkageLength); Frame* cyl1Frame = new PhysicalOffsetFrame(*linkage1, Transform(Vec3(0.0, linkageLength / 2.0, 0.0))); cyl1Frame->setName("Cyl1_frame"); cyl1Frame->attachGeometry(cyl.clone()); osimModel.addFrame(cyl1Frame); // Create a second linkage body as a clone of the first OpenSim::Body* linkage2 = linkage1->clone(); linkage2->setName("linkage2"); Frame* cyl2Frame = new PhysicalOffsetFrame(*linkage2, Transform(Vec3(0.0, linkageLength / 2.0, 0.0))); cyl2Frame->setName("Cyl2_frame"); osimModel.addFrame(cyl2Frame); // Create a block to be the pelvis double blockMass = 20.0, blockSideLength = 0.2; Vec3 blockMassCenter(0); Inertia blockInertia = blockMass*Inertia::brick(blockSideLength, blockSideLength, blockSideLength); OpenSim::Body *block = new OpenSim::Body("block", blockMass, blockMassCenter, blockInertia); block->attachGeometry(new Brick(SimTK::Vec3(0.05, 0.05, 0.05))); // Create 1 degree-of-freedom pin joints between the bodies to create a kinematic chain from ground through the block Vec3 orientationInGround(0), locationInGround(0), locationInParent(0.0, linkageLength, 0.0), orientationInChild(0), locationInChild(0); PinJoint *ankle = new PinJoint("ankle", ground, locationInGround, orientationInGround, *linkage1, locationInChild, orientationInChild); PinJoint *knee = new PinJoint("knee", *linkage1, locationInParent, orientationInChild, *linkage2, locationInChild, orientationInChild); PinJoint *hip = new PinJoint("hip", *linkage2, locationInParent, orientationInChild, *block, locationInChild, orientationInChild); double range[2] = {-SimTK::Pi*2, SimTK::Pi*2}; ankle->updCoordinate().setName("q1"); ankle->updCoordinate().setRange(range); knee->updCoordinate().setName("q2"); knee->updCoordinate().setRange(range); hip->updCoordinate().setName("q3"); hip->updCoordinate().setRange(range); // Add the bodies to the model osimModel.addBody(linkage1); osimModel.addBody(linkage2); osimModel.addBody(block); // Add the joints to the model osimModel.addJoint(ankle); osimModel.addJoint(knee); osimModel.addJoint(hip); // Define constraints on the model // Add a point on line constraint to limit the block to vertical motion Vec3 lineDirection(0,1,0), pointOnLine(0,0,0), pointOnBlock(0); PointOnLineConstraint *lineConstraint = new PointOnLineConstraint(ground, lineDirection, pointOnLine, *block, pointOnBlock); osimModel.addConstraint(lineConstraint); // Add PistonActuator between the first linkage and the block Vec3 pointOnBodies(0); PistonActuator *piston = new PistonActuator(); piston->setName("piston"); piston->setBodyA(linkage1); piston->setBodyB(block); piston->setPointA(pointOnBodies); piston->setPointB(pointOnBodies); piston->setOptimalForce(200.0); piston->setPointsAreGlobal(false); osimModel.addForce(piston); //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Added ControllableSpring between the first linkage and the second block //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ControllableSpring *spring = new ControllableSpring; spring->setName("spring"); spring->setBodyA(block); spring->setBodyB(linkage1); spring->setPointA(pointOnBodies); spring->setPointB(pointOnBodies); spring->setOptimalForce(2000.0); spring->setPointsAreGlobal(false); spring->setRestLength(0.8); osimModel.addForce(spring); // define the simulation times double t0(0.0), tf(15); // create a controller to control the piston and spring actuators // the prescribed controller sets the controls as functions of time PrescribedController *legController = new PrescribedController(); // give the legController control over all (two) model actuators legController->setActuators(osimModel.updActuators()); // specify some control nodes for spring stiffness control double t[] = {0.0, 4.0, 7.0, 10.0, 15.0}; double x[] = {1.0, 1.0, 0.25, 0.25, 5.0}; // specify the control function for each actuator legController->prescribeControlForActuator("piston", new Constant(0.1)); legController->prescribeControlForActuator("spring", new PiecewiseLinearFunction(5, t, x)); // add the controller to the model osimModel.addController(legController); // define the acceleration due to gravity osimModel.setGravity(Vec3(0, -9.80665, 0)); // enable the model visualizer see the model in action, which can be // useful for debugging osimModel.setUseVisualizer(false); // Initialize system SimTK::State& si = osimModel.initSystem(); // Pin joint initial states double q1_i = -Pi/4; double q2_i = - 2*q1_i; CoordinateSet &coordinates = osimModel.updCoordinateSet(); coordinates[0].setValue(si, q1_i, true); coordinates[1].setValue(si,q2_i, true); // Setup integrator and manager SimTK::RungeKuttaMersonIntegrator integrator(osimModel.getMultibodySystem()); integrator.setAccuracy(1.0e-3); ForceReporter *forces = new ForceReporter(&osimModel); osimModel.updAnalysisSet().adoptAndAppend(forces); Manager manager(osimModel, integrator); //Examine the model osimModel.printDetailedInfo(si, std::cout); // Save the model osimModel.print("toyLeg.osim"); // Print out the initial position and velocity states si.getQ().dump("Initial q's"); si.getU().dump("Initial u's"); std::cout << "Initial time: " << si.getTime() << std::endl; // Integrate manager.setInitialTime(t0); manager.setFinalTime(tf); std::cout<<"\n\nIntegrating from " << t0 << " to " << tf << std::endl; manager.integrate(si); // Save results auto controlsTable = osimModel.getControlsTable(); STOFileAdapter_<double>::write(controlsTable, "SpringActuatedLeg_controls.sto"); auto statesTable = manager.getStatesTable(); osimModel.updSimbodyEngine().convertRadiansToDegrees(statesTable); STOFileAdapter_<double>::write(statesTable, "SpringActuatedLeg_states_degrees.sto"); auto forcesTable = forces->getForcesTable(); STOFileAdapter_<double>::write(forcesTable, "actuator_forces.sto"); } catch (const std::exception& ex) { std::cout << "Exception in toyLeg_example: " << ex.what() << std::endl; return 1; } std::cout << "Done." << std::endl; return 0; }