Add Friction In C++ OpenSim Model
- Dídac Coll
- Posts: 8
- Joined: Tue Jan 31, 2017 6:59 pm
Add Friction In C++ OpenSim Model
I'm new in C++ OpenSim library and I'm checking the possibilities of it. My question is I don't know how exactly add friction between two bodies that are connected with a "PinJoint" joint. I've taken a look at class SpringGeneralizedForce but I don't have any idea how to use it. Any help will be grateful.
- Thomas Uchida
- Posts: 1793
- Joined: Wed May 16, 2012 11:40 am
Re: Add Friction In C++ OpenSim Model
The SpringGeneralizedForce is listed in Table B at the bottom of the "Dynamic Walking Challenge: Go the Distance!" example (http://simtk-confluence.stanford.edu:80 ... Id=5113821). A MATLAB script that adds SpringGeneralizedForces to a model can be found here: https://github.com/opensim-org/opensim- ... zedForce.m (the C++ code would be very similar).I've taken a look at class SpringGeneralizedForce but I don't have any idea how to use it.
- Dídac Coll
- Posts: 8
- Joined: Tue Jan 31, 2017 6:59 pm
Re: Add Friction In C++ OpenSim Model
I could find a solution, thanks for the help.
I post the following code in case that somebody is interested in it.
I post the following code in case that somebody is interested in it.
Code: Select all
// Other variables
// PinJoint Initial States
double q1_i = -SimTK::Pi/2, q2_i = 0, q3_i=0;
Model osimModel;
osimModel.setName("pendulumFriction");
osimModel.setAuthors("Dídac Coll");
osimModel.setUseVisualizer(true);
// Set Gravity
SimTK::Vec3 gravity(0, -9.8065, 0);
osimModel.setGravity(gravity);
// Set initial and final simulation time
double initialTime(0.0), finalTime(50.0);
Body& ground = osimModel.getGroundBody();
ground.addDisplayGeometry("checkered_floor.vtp");
double linkMass = 0.1, linkLength = 0.5, linkDiameter = 0.06;
SimTK::Vec3 linkDimensions(linkDiameter, linkLength, linkDiameter);
SimTK::Vec3 linkMassCenter(0, linkLength/2.0, 0);
SimTK::Inertia linkInertia = SimTK::Inertia::cylinderAlongY(linkDiameter/2.0,
linkLength/2.0);
Body* link1 = new Body("link1", linkMass, linkMassCenter,
linkMass*linkInertia);
// Graphical representation
link1->addDisplayGeometry("cylinder.vtp");;
// The "cylinder.vtp" is a 1 m tall, 1 m diameter cylinder need to be scaled
GeometrySet& geometry = link1->updDisplayer()->updGeometrySet();
DisplayGeometry& thinCylinder = geometry[0];
thinCylinder.setScaleFactors(linkDimensions);
thinCylinder.setTransform(Transform(SimTK::Vec3(0.0, linkLength/2.0, 0.0)));
// Add a sphere
link1->addDisplayGeometry("sphere.vtp");
// This "sphere.vtp" is 1 meter in diameter. Need to be scaled
geometry[1].setScaleFactors(SimTK::Vec3(0.1));
// Create the second link
Body* link2 = new Body(*link1); // Create a new object link2 copying the first one
link2->setName("link2"); // Set hte name of the body
// Create a block to be the pelvis
double blockMass = 20.0, blockSideLength = 0.2;
SimTK::Vec3 blockMassCenter(0);
SimTK::Inertia blockInertia = blockMass*SimTK::Inertia::brick(blockSideLength,
blockSideLength,
blockSideLength);
Body* pelvis = new Body("pelvis", blockMass, blockMassCenter, blockInertia);
pelvis->addDisplayGeometry("block.vtp");
// Scale it is 0.1 x 0.1 x 0.1 m
pelvis->updDisplayer()->updGeometrySet()[0].setScaleFactors(SimTK::Vec3(2.0));
// Create 1 degree-of-freedom pin joints between the bodies to create a kinematic chain
SimTK::Vec3 orientationInGround(0), locationInGround(0), locationInParent(0.0, linkLength, 0.0),
orientationInChild(0), locationInChild(0);
PinJoint *ankle = new PinJoint("ankle", ground, locationInGround,
orientationInGround, *link1,
locationInChild, orientationInChild);
PinJoint *knee = new PinJoint("knee", *link1, locationInParent,
orientationInChild, *link2,
locationInChild, orientationInChild);
PinJoint *hip = new PinJoint("hip", *link2, locationInParent,
orientationInChild, *pelvis,
locationInChild, orientationInChild);
double range[2] = {-SimTK::Pi*2, SimTK::Pi*2};
CoordinateSet& ankleCoordinateSet = ankle->upd_CoordinateSet();
ankleCoordinateSet[0].setName("q1");
ankleCoordinateSet[0].setRange(range);
CoordinateSet& kneeCoordinateSet = knee->upd_CoordinateSet();
kneeCoordinateSet[0].setName("q2");
kneeCoordinateSet[0].setRange(range);
CoordinateSet& hipCoordinateSet = hip->upd_CoordinateSet();
hipCoordinateSet[0].setName("q3");
hipCoordinateSet[0].setRange(range);
// Add all the bodies to the model
osimModel.addBody(link1);
osimModel.addBody(link2);
osimModel.addBody(pelvis);
SimTK::State& si = osimModel.initSystem();
osimModel.printDetailedInfo(si, cout);
// Obtain the mobilizedBodies
SimTK::MobilizedBodyIndex mobIndex(0);
const SimTK::MobilizedBody& moTibia =
osimModel.getMatterSubsystem().getMobilizedBody(mobIndex);
mobIndex++;
const SimTK::MobilizedBody& moFemur =
osimModel.getMatterSubsystem().getMobilizedBody(mobIndex);
// Add friction forces
SimTK::MultibodySystem& system = osimModel.updMultibodySystem();
SimTK::GeneralForceSubsystem& forces = osimModel.updForceSubsystem();
SimTK::Force::MobilityLinearDamper frictionAnkle (forces, // GeneralForceSubsystem
moTibia,// MobilizedBody
SimTK::MobilizerUIndex(0), // whichU
2.5 // Real or constant k
);
SimTK::Force::MobilityLinearDamper frictionKnee (forces,
moFemur,
SimTK::MobilizerUIndex(0),
0.1);
//////////////////////////
// PERFORM A SIMULATION //
//////////////////////////
// Set Up Visualizer
osimModel.updMatterSubsystem().setShowDefaultGeometry(true);
SimTK::Visualizer& viz = osimModel.updVisualizer().updSimbodyVisualizer();
viz.setBackgroundColor(SimTK::Black); // Set background colour
si = osimModel.initializeState();
// Set translation in y all blocks
ankleCoordinateSet[0].setValue(si, 0.01);
kneeCoordinateSet[0].setValue(si, 0.01);
hipCoordinateSet[0].setValue(si, 0.01);
CoordinateSet &coordinates = osimModel.updCoordinateSet();
coordinates[0].setValue(si, q1_i, true);
coordinates[1].setValue(si, q2_i, true);
coordinates[2].setValue(si, q3_i, true);
// Run the simulation
SimTK::RungeKuttaMersonIntegrator integrator(osimModel.getMultibodySystem());
Manager manager(osimModel, integrator);
manager.setInitialTime(initialTime); manager.setFinalTime(finalTime);
manager.integrate(si);