void testLoadObjFile() { string file; file += "# This is a comment\n"; file += "v -1.0 1.0 2.0\n"; file += "v -2.0 2.0 3.0\n"; file += "v -3.0 3.0 \\\n"; file += "4.0\n"; file += "v -4.0 4.0 5.0\n"; file += "v -5.0 5.0 6.0\n"; file += "f 1 2 3\n"; file += "f 2// 3/4/5 4//2\n"; file += "f -3 -2/3/4 -1\n"; file += "f 1 3\\\n"; file += "5 2\n"; PolygonalMesh mesh; stringstream stream(file); mesh.loadObjFile(stream); ASSERT(mesh.getNumVertices() == 5); ASSERT(mesh.getNumFaces() == 4); for (int i = 0; i < mesh.getNumVertices(); i++) { const Vec3& pos = mesh.getVertexPosition(i); ASSERT(pos[0] == -(i+1)); ASSERT(pos[1] == i+1); ASSERT(pos[2] == i+2); } for (int i = 0; i < 3; i++) { ASSERT(mesh.getNumVerticesForFace(i) == 3); ASSERT(mesh.getFaceVertex(i, 0) == i); ASSERT(mesh.getFaceVertex(i, 1) == i+1); ASSERT(mesh.getFaceVertex(i, 2) == i+2); } ASSERT(mesh.getNumVerticesForFace(3) == 4); ASSERT(mesh.getFaceVertex(3, 0) == 0); ASSERT(mesh.getFaceVertex(3, 1) == 2); ASSERT(mesh.getFaceVertex(3, 2) == 4); ASSERT(mesh.getFaceVertex(3, 3) == 1); }
void flexionFDSimulationWithHitMap(Model& model) { addFlexionController(model); //addExtensionController(model); //addTibialLoads(model, 0); model.setUseVisualizer(true); // init system std::time_t result = std::time(nullptr); std::cout << "\nBefore initSystem() " << std::asctime(std::localtime(&result)) << endl; SimTK::State& si = model.initSystem(); result = std::time(nullptr); std::cout << "\nAfter initSystem() " << std::asctime(std::localtime(&result)) << endl; // set gravity //model.updGravityForce().setGravityVector(si, Vec3(-9.80665,0,0)); //model.updGravityForce().setGravityVector(si, Vec3(0,0,0)); //setHipAngle(model, si, 90); //setKneeAngle(model, si, 0, false, false); //model.equilibrateMuscles( si); MultibodySystem& system = model.updMultibodySystem(); SimbodyMatterSubsystem& matter = system.updMatterSubsystem(); GeneralForceSubsystem forces(system); ContactTrackerSubsystem tracker(system); CompliantContactSubsystem contactForces(system, tracker); contactForces.setTrackDissipatedEnergy(true); //contactForces.setTransitionVelocity(1e-3); for (int i=0; i < matter.getNumBodies(); ++i) { MobilizedBodyIndex mbx(i); if (i==19 || i==20 || i==22)// || i==15 || i==16) { MobilizedBody& mobod = matter.updMobilizedBody(mbx); std::filebuf fb; //cout << mobod.updBody(). if (i==19) fb.open ( "../resources/femur_lat_r.obj",std::ios::in); else if (i==20) fb.open ( "../resources/femur_med_r.obj",std::ios::in); else if (i==22) fb.open ( "../resources/tibia_upper_r.obj",std::ios::in); //else if (i==15) //fb.open ( "../resources/meniscus_lat_r.obj",std::ios::in); //else if (i==16) //fb.open ( "../resources/meniscus_med_r.obj",std::ios::in); std::istream is(&fb); PolygonalMesh polMesh; polMesh.loadObjFile(is); fb.close(); SimTK::ContactGeometry::TriangleMesh mesh(polMesh); ContactSurface contSurf;//(mesh, ContactMaterial(1.0e6, 1, 1, 0.03, 0.03), 0.001); if (i==19 || i==20 || i==22) contSurf = ContactSurface(mesh, ContactMaterial(10, 1, 1, 0.03, 0.03), 0.001); //else if (i==15 || i==16) //contSurf = ContactSurface(mesh, ContactMaterial(10, 3, 1, 0.03, 0.03), 0.001); DecorativeMesh showMesh(mesh.createPolygonalMesh()); showMesh.setOpacity(0.5); mobod.updBody().addDecoration( showMesh); mobod.updBody().addContactSurface(contSurf); } } ModelVisualizer& viz(model.updVisualizer()); //Visualizer viz(system); viz.updSimbodyVisualizer().addDecorationGenerator(new HitMapGenerator(system,contactForces)); viz.updSimbodyVisualizer().setMode(Visualizer::RealTime); viz.updSimbodyVisualizer().setDesiredBufferLengthInSec(1); viz.updSimbodyVisualizer().setDesiredFrameRate(30); viz.updSimbodyVisualizer().setGroundHeight(-3); viz.updSimbodyVisualizer().setShowShadows(true); Visualizer::InputSilo* silo = new Visualizer::InputSilo(); viz.updSimbodyVisualizer().addInputListener(silo); Array_<std::pair<String,int> > runMenuItems; runMenuItems.push_back(std::make_pair("Go", GoItem)); runMenuItems.push_back(std::make_pair("Replay", ReplayItem)); runMenuItems.push_back(std::make_pair("Quit", QuitItem)); viz.updSimbodyVisualizer().addMenu("Run", RunMenuId, runMenuItems); Array_<std::pair<String,int> > helpMenuItems; helpMenuItems.push_back(std::make_pair("TBD - Sorry!", 1)); viz.updSimbodyVisualizer().addMenu("Help", HelpMenuId, helpMenuItems); system.addEventReporter(new MyReporter(system,contactForces,ReportInterval)); //system.addEventReporter(new Visualizer::Reporter(viz.updSimbodyVisualizer(), ReportInterval)); // Check for a Run->Quit menu pick every <x> second. system.addEventHandler(new UserInputHandler(*silo, 0.001)); system.realizeTopology(); //Show ContactSurfaceIndex for each contact surface // for (int i=0; i < matter.getNumBodies(); ++i) { //MobilizedBodyIndex mbx(i); // const MobilizedBody& mobod = matter.getMobilizedBody(mbx); // const int nsurfs = mobod.getBody().getNumContactSurfaces(); //printf("mobod %d has %d contact surfaces\n", (int)mbx, nsurfs); ////cout << "mobod with mass: " << (float)mobod.getBodyMass(si) << " has " << nsurfs << " contact surfaces" << endl; // //for (int i=0; i<nsurfs; ++i) { // //printf("%2d: index %d\n", i, // //(int)tracker.getContactSurfaceIndex(mbx,i)); // //} // } //cout << "tracker num of surfaces: " << tracker.getNumSurfaces() << endl; //State state = system.getDefaultState(); //viz.report(state); State& state = model.initializeState(); viz.updSimbodyVisualizer().report(state); // Add reporters ForceReporter* forceReporter = new ForceReporter(&model); model.addAnalysis(forceReporter); CustomAnalysis* customReporter = new CustomAnalysis(&model, "r"); model.addAnalysis(customReporter); // Create the integrator and manager for the simulation. SimTK::RungeKuttaMersonIntegrator integrator(model.getMultibodySystem()); //SimTK::CPodesIntegrator integrator(model.getMultibodySystem()); //integrator.setAccuracy(.01); //integrator.setAccuracy(1e-3); //integrator.setFixedStepSize(0.001); Manager manager(model, integrator); // Define the initial and final simulation times double initialTime = 0.0; double finalTime = 0.2; // Integrate from initial time to final time manager.setInitialTime(initialTime); manager.setFinalTime(finalTime); std::cout<<"\n\nIntegrating from "<<initialTime<<" to " <<finalTime<<std::endl; result = std::time(nullptr); std::cout << "\nBefore integrate(si) " << std::asctime(std::localtime(&result)) << endl; manager.integrate(state); result = std::time(nullptr); std::cout << "\nAfter integrate(si) " << std::asctime(std::localtime(&result)) << endl; // Save the simulation results Storage statesDegrees(manager.getStateStorage()); statesDegrees.print("../outputs/states_flex.sto"); model.updSimbodyEngine().convertRadiansToDegrees(statesDegrees); statesDegrees.setWriteSIMMHeader(true); statesDegrees.print("../outputs/states_degrees_flex.mot"); // force reporter results forceReporter->getForceStorage().print("../outputs/force_reporter_flex.mot"); //customReporter->print( "../outputs/custom_reporter_flex.mot"); //cout << "You can choose 'Replay'" << endl; int menuId, item; unsigned int frameRate = 5; do { cout << "Please choose 'Replay' or 'Quit'" << endl; viz.updInputSilo().waitForMenuPick(menuId, item); if (item != ReplayItem && item != QuitItem) cout << "\aDude... follow instructions!\n"; if (item == ReplayItem) { cout << "Type desired frame rate (integer) for playback and press Enter (default = 1) : "; //frameRate = cin.get(); cin >> frameRate; if (cin.fail()) { cout << "Not an int. Setting default frame rate." << endl; cin.clear(); cin.ignore(std::numeric_limits<int>::max(),'\n'); frameRate = 1; } //cout << "saveEm size: " << saveEm.size() << endl; for (unsigned int i=0; i<saveEm.size(); i++) { viz.updSimbodyVisualizer().drawFrameNow(saveEm.getElt(i)); if (frameRate == 0) frameRate = 1; usleep(1000000/frameRate); } } } while (menuId != RunMenuId || item != QuitItem); }
int main() { try { std::cout << "Current working directory: " << Pathname::getCurrentWorkingDirectory() << std::endl; // Create the system. MultibodySystem system; system.setUseUniformBackground(true); SimbodyMatterSubsystem matter(system); GeneralForceSubsystem forces(system); Force::UniformGravity gravity(forces, matter, 0*Vec3(2, -9.8, 0)); ContactTrackerSubsystem tracker(system); CompliantContactSubsystem contactForces(system, tracker); contactForces.setTrackDissipatedEnergy(true); GeneralContactSubsystem OLDcontact(system); const ContactSetIndex OLDcontactSet = OLDcontact.createContactSet(); contactForces.setTransitionVelocity(1e-3); std::ifstream meshFile1, meshFile2; PolygonalMesh femurMesh; meshFile1.open("ContactBigMeshes_Femur.obj"); femurMesh.loadObjFile(meshFile1); meshFile1.close(); PolygonalMesh patellaMesh; meshFile2.open("ContactBigMeshes_Patella.obj"); patellaMesh.loadObjFile(meshFile2); meshFile2.close(); ContactGeometry::TriangleMesh femurTri(femurMesh); ContactGeometry::TriangleMesh patellaTri(patellaMesh); DecorativeMesh showFemur(femurTri.createPolygonalMesh()); Array_<DecorativeLine> femurNormals; const Real NormalLength = .02; //for (int fx=0; fx < femurTri.getNumFaces(); ++fx) // femurNormals.push_back( // DecorativeLine(femurTri.findCentroid(fx), // femurTri.findCentroid(fx) // + NormalLength*femurTri.getFaceNormal(fx))); DecorativeMesh showPatella(patellaTri.createPolygonalMesh()); Array_<DecorativeLine> patellaNormals; //for (int fx=0; fx < patellaTri.getNumFaces(); ++fx) // patellaNormals.push_back( // DecorativeLine(patellaTri.findCentroid(fx), // patellaTri.findCentroid(fx) // + NormalLength*patellaTri.getFaceNormal(fx))); // This transform has the meshes close enough that their OBBs overlap // but in the end none of the faces are touching. const Transform X_FP( Rotation(Mat33( 0.97107625831404454, 0.23876955530133021, 0, -0.23876955530133021, 0.97107625831404454, 0, 0, 0, 1), true), Vec3(0.057400580865008571, 0.43859170879135373, -0.00016506240185135300) ); const Real fFac =1; // to turn off friction const Real fDis = .5*0.2; // to turn off dissipation const Real fVis = .1*.1; // to turn off viscous friction const Real fK = 100*1e6; // pascals // Put femur on ground at origin matter.Ground().updBody().addDecoration(Vec3(0,0,0), showFemur.setColor(Cyan).setOpacity(.2)); matter.Ground().updBody().addContactSurface(Vec3(0,0,0), ContactSurface(femurTri, ContactMaterial(fK*.01,fDis*.9,fFac*.8,fFac*.7,fVis*10), .01 /*thickness*/)); Body::Rigid patellaBody(MassProperties(1.0, Vec3(0), Inertia(1))); patellaBody.addDecoration(Transform(), showPatella.setColor(Red).setOpacity(.2)); patellaBody.addContactSurface(Transform(), ContactSurface(patellaTri, ContactMaterial(fK*.001,fDis*.9,fFac*.8,fFac*.7,fVis*10), .01 /*thickness*/)); MobilizedBody::Free patella(matter.Ground(), Transform(Vec3(0)), patellaBody, Transform(Vec3(0))); //// The old way ... //OLDcontact.addBody(OLDcontactSet, ball, // pyramid, Transform()); //OLDcontact.addBody(OLDcontactSet, matter.updGround(), // ContactGeometry::HalfSpace(), Transform(R_xdown, Vec3(0,-3,0))); //ElasticFoundationForce ef(forces, OLDcontact, OLDcontactSet); //Real stiffness = 1e6, dissipation = 0.01, us = 0.1, // ud = 0.05, uv = 0.01, vt = 0.01; ////Real stiffness = 1e6, dissipation = 0.1, us = 0.8, //// ud = 0.7, uv = 0.01, vt = 0.01; //ef.setBodyParameters(ContactSurfaceIndex(0), // stiffness, dissipation, us, ud, uv); //ef.setTransitionVelocity(vt); //// end of old way. Visualizer viz(system); Visualizer::Reporter& reporter = *new Visualizer::Reporter(viz, ReportInterval); viz.addDecorationGenerator(new ForceArrowGenerator(system,contactForces)); MyReporter& myRep = *new MyReporter(system,contactForces,ReportInterval); system.addEventReporter(&myRep); system.addEventReporter(&reporter); // Initialize the system and state. system.realizeTopology(); State state = system.getDefaultState(); viz.report(state); printf("Reference state -- hit ENTER\n"); cout << "t=" << state.getTime() << " q=" << patella.getQAsVector(state) << " u=" << patella.getUAsVector(state) << endl; char c=getchar(); patella.setQToFitTransform(state, ~X_FP); viz.report(state); printf("Initial state -- hit ENTER\n"); cout << "t=" << state.getTime() << " q=" << patella.getQAsVector(state) << " u=" << patella.getUAsVector(state) << endl; c=getchar(); // Simulate it. const clock_t start = clock(); RungeKutta3Integrator integ(system); TimeStepper ts(system, integ); ts.initialize(state); ts.stepTo(2.0); const double timeInSec = (double)(clock()-start)/CLOCKS_PER_SEC; const int evals = integ.getNumRealizations(); cout << "Done -- took " << integ.getNumStepsTaken() << " steps in " << timeInSec << "s for " << ts.getTime() << "s sim (avg step=" << (1000*ts.getTime())/integ.getNumStepsTaken() << "ms) " << (1000*ts.getTime())/evals << "ms/eval\n"; printf("Using Integrator %s at accuracy %g:\n", integ.getMethodName(), integ.getAccuracyInUse()); printf("# STEPS/ATTEMPTS = %d/%d\n", integ.getNumStepsTaken(), integ.getNumStepsAttempted()); printf("# ERR TEST FAILS = %d\n", integ.getNumErrorTestFailures()); printf("# REALIZE/PROJECT = %d/%d\n", integ.getNumRealizations(), integ.getNumProjections()); while(true) { for (int i=0; i < (int)saveEm.size(); ++i) { viz.report(saveEm[i]); } getchar(); } } catch (const std::exception& e) { std::printf("EXCEPTION THROWN: %s\n", e.what()); exit(1); } catch (...) { std::printf("UNKNOWN EXCEPTION THROWN\n"); exit(1); } return 0; }