Add Friction In C++ OpenSim Model

Provide easy-to-use, extensible software for modeling, simulating, controlling, and analyzing the neuromusculoskeletal system.
POST REPLY
User avatar
Dídac Coll
Posts: 8
Joined: Tue Jan 31, 2017 6:59 pm

Add Friction In C++ OpenSim Model

Post by Dídac Coll » Wed Mar 29, 2017 7:31 am

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.

User avatar
Thomas Uchida
Posts: 1789
Joined: Wed May 16, 2012 11:40 am

Re: Add Friction In C++ OpenSim Model

Post by Thomas Uchida » Fri Mar 31, 2017 7:51 pm

I've taken a look at class SpringGeneralizedForce but I don't have any idea how to use it.
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).

User avatar
Dídac Coll
Posts: 8
Joined: Tue Jan 31, 2017 6:59 pm

Re: Add Friction In C++ OpenSim Model

Post by Dídac Coll » Mon Apr 03, 2017 8:50 am

I could find a solution, thanks for the help.

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);
      

POST REPLY