void testSpeedCoupler2() { // Create a system involving a constraint that affects three different // bodies. MultibodySystem system; SimbodyMatterSubsystem matter(system); createGimbalSystem(system); MobilizedBody& first = matter.updMobilizedBody(MobilizedBodyIndex(1)); std::vector<MobilizedBodyIndex> bodies(3); std::vector<MobilizerUIndex> speeds(3); bodies[0] = MobilizedBodyIndex(1); bodies[1] = MobilizedBodyIndex(3); bodies[2] = MobilizedBodyIndex(5); speeds[0] = MobilizerUIndex(0); speeds[1] = MobilizerUIndex(0); speeds[2] = MobilizerUIndex(1); Function* function = new CompoundFunction(); Constraint::SpeedCoupler coupler(matter, function, bodies, speeds); State state; createState(system, state); // Make sure the constraint is satisfied. Vector args(function->getArgumentSize()); for (int i = 0; i < args.size(); ++i) args[i] = matter.getMobilizedBody(bodies[i]).getOneU(state, speeds[i]); SimTK_TEST_EQ(0.0, function->calcValue(args)); // Simulate it and make sure the constraint is working correctly and // energy is being conserved. This should be workless and power should // always be zero (to the extent that the constraint is satisfied). Real energy0 = system.calcEnergy(state); RungeKuttaMersonIntegrator integ(system); integ.setAccuracy(1e-6); integ.setReturnEveryInternalStep(true); integ.initialize(state); while (integ.getTime() < 10.0) { integ.stepTo(10.0); const State& istate = integ.getState(); system.realize(istate, Stage::Acceleration); const Real energy = system.calcEnergy(istate); const Real power = coupler.calcPower(istate); for (int i = 0; i < args.size(); ++i) args[i] = matter.getMobilizedBody(bodies[i]).getOneU(istate, speeds[i]); SimTK_TEST_EQ_TOL(0.0, function->calcValue(args), integ.getConstraintToleranceInUse()); SimTK_TEST_EQ_TOL(0.0, power, 10*integ.getConstraintToleranceInUse()); // Energy conservation depends on global integration accuracy; // accuracy returned here is local so we'll fudge at 10X. const Real etol = 10*integ.getAccuracyInUse() *std::max(std::abs(energy), std::abs(energy0)); SimTK_TEST_EQ_TOL(energy0, energy, etol); } }
void testCoordinateCoupler3() { // Create a system involving a constrained body for which qdot != u. MultibodySystem system; SimbodyMatterSubsystem matter(system); createBallSystem(system); MobilizedBody& first = matter.updMobilizedBody(MobilizedBodyIndex(1)); std::vector<MobilizedBodyIndex> bodies(3); std::vector<MobilizerQIndex> coordinates(3); bodies[0] = MobilizedBodyIndex(1); bodies[1] = MobilizedBodyIndex(1); bodies[2] = MobilizedBodyIndex(1); coordinates[0] = MobilizerQIndex(0); coordinates[1] = MobilizerQIndex(1); coordinates[2] = MobilizerQIndex(2); Function* function = new CompoundFunction(); Constraint::CoordinateCoupler coupler(matter, function, bodies, coordinates); State state; createState(system, state); // Make sure the constraint is satisfied. Vector args(function->getArgumentSize()); for (int i = 0; i < args.size(); ++i) args[i] = matter.getMobilizedBody(bodies[i]).getOneQ(state, coordinates[i]); SimTK_TEST_EQ(0.0, function->calcValue(args)); // Simulate it and make sure the constraint is working correctly and // energy is being conserved. const Real energy0 = system.calcEnergy(state); RungeKuttaMersonIntegrator integ(system); integ.setReturnEveryInternalStep(true); integ.initialize(state); while (integ.getTime() < 10.0) { integ.stepTo(10.0); const State& istate = integ.getState(); const Real energy = system.calcEnergy(istate); for (int i = 0; i < args.size(); ++i) args[i] = matter.getMobilizedBody(bodies[i]) .getOneQ(integ.getState(), coordinates[i]); // Constraints are applied to unnormalized quaternions. When they are // normalized, that can increase the constraint error. That is why we // need the factor of 3 in the next line. // TODO: Huh? (sherm) SimTK_TEST_EQ_TOL(0.0, function->calcValue(args), 3*integ.getConstraintToleranceInUse()); // Energy conservation depends on global integration accuracy; // accuracy returned here is local so we'll fudge at 10X. const Real etol = 10*integ.getAccuracyInUse() *std::max(std::abs(energy), std::abs(energy0)); SimTK_TEST_EQ_TOL(energy0, energy, etol); } }
void testPrescribedMotion1() { // Create a system requiring simple linear motion of one Q. This // may require that the constraint do work. // (The way the cylinder system is structured it only takes work to // keep body one at a uniform velocity; the rest are in free fall.) MultibodySystem system; SimbodyMatterSubsystem matter(system); createCylinderSystem(system); MobilizedBodyIndex body = MobilizedBodyIndex(1); MobilizerQIndex coordinate = MobilizerQIndex(1); Vector coefficients(2); coefficients[0] = 0.1; coefficients[1] = 0.0; Function* function = new Function::Linear(coefficients); Constraint::PrescribedMotion constraint(matter, function, body, coordinate); PowerMeasure<Real> powMeas(matter, constraint); Measure::Zero zeroMeas(matter); Measure::Integrate workMeas(matter, powMeas, zeroMeas); State state; createState(system, state); workMeas.setValue(state, 0); // override createState // Make sure the constraint is satisfied. Vector args(1, state.getTime()); SimTK_TEST_EQ(function->calcValue(args), matter.getMobilizedBody(body).getOneQ(state, coordinate)); // Simulate it and make sure the constraint is working correctly. const Real energy0 = system.calcEnergy(state); RungeKuttaMersonIntegrator integ(system); integ.setReturnEveryInternalStep(true); integ.initialize(state); while (integ.getTime() < 10.0) { integ.stepTo(10.0); const State& istate = integ.getState(); system.realize(istate, Stage::Acceleration); const Real energy = system.calcEnergy(istate); const Real power = powMeas.getValue(istate); const Real work = workMeas.getValue(istate); Vector args(1, istate.getTime()); const Real q = matter.getMobilizedBody(body).getOneQ(istate, coordinate); SimTK_TEST_EQ_TOL(function->calcValue(args), q, integ.getConstraintToleranceInUse()); // Energy conservation depends on global integration accuracy; // accuracy returned here is local so we'll fudge at 10X. const Real etol = 10*integ.getAccuracyInUse() *std::max(std::abs(energy-work), std::abs(energy0)); SimTK_TEST_EQ_TOL(energy0, energy-work, etol) } }
int main(int argc, char** argv) { static const Transform GroundFrame; static const Rotation ZUp(UnitVec3(XAxis), XAxis, UnitVec3(YAxis), ZAxis); static const Vec3 TestLoc(1,0,0); try { // If anything goes wrong, an exception will be thrown. // CREATE MULTIBODY SYSTEM AND ITS SUBSYSTEMS MultibodySystem mbs; SimbodyMatterSubsystem matter(mbs); GeneralForceSubsystem forces(mbs); DecorationSubsystem viz(mbs); //Force::UniformGravity gravity(forces, matter, Vec3(0, -g, 0)); // ADD BODIES AND THEIR MOBILIZERS Body::Rigid particle = Body::Rigid(MassProperties(m, Vec3(0), Inertia(0))); particle.addDecoration(DecorativeSphere(.1).setColor(Red).setOpacity(.3)); MobilizedBody::SphericalCoords anAtom(matter.Ground(), Transform(ZUp, TestLoc), particle, Transform(), 0*Deg2Rad, false, // azimuth offset, negated 0, false, // zenith offset, negated ZAxis, true); // translation axis, negated anAtom.setDefaultRadius(.1); anAtom.setDefaultAngles(Vec2(0, 30*Deg2Rad)); viz.addRubberBandLine(matter.Ground(), TestLoc, anAtom, Vec3(0), DecorativeLine().setColor(Orange).setLineThickness(4)); Force::MobilityLinearSpring(forces, anAtom, 0, 2, -30*Deg2Rad); // harmonic bend Force::MobilityLinearSpring(forces, anAtom, 1, 2, 45*Deg2Rad); // harmonic bend Force::MobilityLinearSpring(forces, anAtom, 2, 20, .5); // harmonic stretch Force::MobilityLinearDamper(forces, anAtom, 0, .1); // harmonic bend Force::MobilityLinearDamper(forces, anAtom, 1, .1); // harmonic bend Force::MobilityLinearDamper(forces, anAtom, 2, .1); // harmonic stretch State s = mbs.realizeTopology(); // returns a reference to the the default state mbs.realizeModel(s); // define appropriate states for this System mbs.realize(s, Stage::Instance); // instantiate constraints if any Visualizer display(mbs); display.setBackgroundType(Visualizer::SolidColor); mbs.realize(s, Stage::Velocity); display.report(s); cout << "q=" << s.getQ() << endl; cout << "u=" << s.getU() << endl; char c; cout << "Default configuration shown. 1234 to move on.\n"; //anAtom.setQToFitRotation(s, Rotation(-.9*Pi/2,YAxis)); while (true) { Real x; cout << "Torsion (deg)? "; cin >> x; if (x==1234) break; Vec2 a = anAtom.getAngles(s); a[0]=x*Deg2Rad; anAtom.setAngles(s, a); display.report(s); cout << "Bend (deg)? "; cin >> x; if (x==1234) break; a = anAtom.getAngles(s); a[1]=x*Deg2Rad; anAtom.setAngles(s, a); display.report(s); cout << "Radius? "; cin >> x; if (x==1234) break; anAtom.setRadius(s, x); display.report(s); } anAtom.setUToFitAngularVelocity(s, Vec3(.1,.2,.3)); //anAtom.setAngle(s, 45*Deg2Rad); //anAtom.setTranslation(s, Vec2(.4, .1)); mbs.realize(s, Stage::Dynamics); mbs.realize(s, Stage::Acceleration); cout << "q=" << s.getQ() << endl; cout << "u=" << s.getU() << endl; cout << "qdot=" << s.getQDot() << endl; cout << "udot=" << s.getUDot() << endl; cout << "qdotdot=" << s.getQDotDot() << endl; display.report(s); cout << "Initialized configuration shown. Ready? "; cin >> c; RungeKuttaMersonIntegrator myStudy(mbs); myStudy.setAccuracy(1e-4); const Real dt = .02; // output intervals const Real finalTime = 20; myStudy.setFinalTime(finalTime); // Peforms assembly if constraints are violated. myStudy.initialize(s); cout << "Using Integrator " << std::string(myStudy.getMethodName()) << ":\n"; cout << "ACCURACY IN USE=" << myStudy.getAccuracyInUse() << endl; cout << "CTOL IN USE=" << myStudy.getConstraintToleranceInUse() << endl; cout << "TIMESCALE=" << mbs.getDefaultTimeScale() << endl; cout << "U WEIGHTS=" << s.getUWeights() << endl; cout << "Z WEIGHTS=" << s.getZWeights() << endl; cout << "1/QTOLS=" << s.getQErrWeights() << endl; cout << "1/UTOLS=" << s.getUErrWeights() << endl; Integrator::SuccessfulStepStatus status; int nextReport = 0; while ((status=myStudy.stepTo(nextReport*dt)) != Integrator::EndOfSimulation) { const State& s = myStudy.getState(); mbs.realize(s); printf("%5g %10.4g %10.4g %10.4g E=%10.8g h%3d=%g %s%s\n", s.getTime(), anAtom.getAngles(s)[0], anAtom.getAngles(s)[1], anAtom.getRadius(s), //anAtom.getAngle(s), anAtom.getTranslation(s)[0], anAtom.getTranslation(s)[1], //anAtom.getQ(s)[0], anAtom.getQ(s)[1], anAtom.getQ(s)[2], mbs.calcEnergy(s), myStudy.getNumStepsTaken(), myStudy.getPreviousStepSizeTaken(), Integrator::getSuccessfulStepStatusString(status).c_str(), myStudy.isStateInterpolated()?" (INTERP)":""); display.report(s); if (status == Integrator::ReachedReportTime) ++nextReport; } printf("Using Integrator %s:\n", myStudy.getMethodName()); printf("# STEPS/ATTEMPTS = %d/%d\n", myStudy.getNumStepsTaken(), myStudy.getNumStepsAttempted()); printf("# ERR TEST FAILS = %d\n", myStudy.getNumErrorTestFailures()); printf("# REALIZE/PROJECT = %d/%d\n", myStudy.getNumRealizations(), myStudy.getNumProjections()); } catch (const std::exception& e) { printf("EXCEPTION THROWN: %s\n", e.what()); exit(1); } catch (...) { printf("UNKNOWN EXCEPTION THROWN\n"); exit(1); } }
int main(int argc, char** argv) { std::vector<State> saveEm; saveEm.reserve(1000); try // If anything goes wrong, an exception will be thrown. { int nseg = NSegments; int shouldFlop = 0; if (argc > 1) sscanf(argv[1], "%d", &nseg); if (argc > 2) sscanf(argv[2], "%d", &shouldFlop); // Create a multibody system using Simbody. MultibodySystem mbs; MyRNAExample myRNA(mbs, nseg, shouldFlop != 0); GeneralForceSubsystem forces(mbs); Force::UniformGravity ugs(forces, myRNA, Vec3(0, -g, 0), -0.8); const Vec3 attachPt(150, -40, -50); Force::TwoPointLinearSpring(forces, myRNA.Ground(), attachPt, myRNA.getMobilizedBody(MobilizedBodyIndex(myRNA.getNumBodies()-1)), Vec3(0), 1000., // stiffness 1.); // natural length Force::GlobalDamper(forces, myRNA, 1000); State s = mbs.realizeTopology(); //myRNA.getConstraint(ConstraintIndex(myRNA.getNConstraints()-4)).disable(s); //myRNA.setUseEulerAngles(s,true); mbs.realizeModel(s); mbs.realize(s, Stage::Position); for (ConstraintIndex cid(0); cid < myRNA.getNumConstraints(); ++cid) { const Constraint& c = myRNA.getConstraint(cid); int mp,mv,ma; c.getNumConstraintEquationsInUse(s, mp,mv,ma); cout << "CONSTRAINT " << cid << " constrained bodies=" << c.getNumConstrainedBodies() << " ancestor=" << c.getAncestorMobilizedBody().getMobilizedBodyIndex() << " constrained mobilizers/nq/nu=" << c.getNumConstrainedMobilizers() << "/" << c.getNumConstrainedQ(s) << "/" << c.getNumConstrainedU(s) << " mp,mv,ma=" << mp << "," << mv << "," << ma << endl; for (ConstrainedBodyIndex cid(0); cid < c.getNumConstrainedBodies(); ++cid) { cout << " constrained body: " << c.getMobilizedBodyFromConstrainedBody(cid).getMobilizedBodyIndex(); cout << endl; } for (ConstrainedMobilizerIndex cmx(0); cmx < c.getNumConstrainedMobilizers(); ++cmx) { cout << " constrained mobilizer " << c.getMobilizedBodyFromConstrainedMobilizer(cmx).getMobilizedBodyIndex() << ", q(" << c.getNumConstrainedQ(s, cmx) << ")="; for (MobilizerQIndex i(0); i < c.getNumConstrainedQ(s, cmx); ++i) cout << " " << c.getConstrainedQIndex(s, cmx, i); cout << ", u(" << c.getNumConstrainedU(s, cmx) << ")="; for (MobilizerUIndex i(0); i < c.getNumConstrainedU(s, cmx); ++i) cout << " " << c.getConstrainedUIndex(s, cmx, i); cout << endl; } cout << c.getSubtree(); cout << " d(perrdot)/du=" << c.calcPositionConstraintMatrixP(s); cout << " d(perrdot)/du=" << ~c.calcPositionConstraintMatrixPt(s); cout << " d(perr)/dq=" << c.calcPositionConstraintMatrixPNInv(s); } SimbodyMatterSubtree sub(myRNA); sub.addTerminalBody(myRNA.getMobilizedBody(MobilizedBodyIndex(7))); sub.addTerminalBody(myRNA.getMobilizedBody(MobilizedBodyIndex(10))); //sub.addTerminalBody(myRNA.getMobilizedBody(MobilizedBodyIndex(20))); sub.realizeTopology(); cout << "sub.ancestor=" << sub.getAncestorMobilizedBodyIndex(); // cout << " sub.terminalBodies=" << sub.getTerminalBodies() << endl; // cout << "sub.allBodies=" << sub.getAllBodies() << endl; for (SubtreeBodyIndex i(0); i < (int)sub.getAllBodies().size(); ++i) { cout << "sub.parent[" << i << "]=" << sub.getParentSubtreeBodyIndex(i); // cout << " sub.children[" << i << "]=" << sub.getChildSubtreeBodyIndexs(i) << endl; } printf("# quaternions in use = %d\n", myRNA.getNumQuaternionsInUse(s)); for (MobilizedBodyIndex i(0); i<myRNA.getNumBodies(); ++i) { printf("body %2d: using quat? %s; quat index=%d\n", (int)i, myRNA.isUsingQuaternion(s,i) ? "true":"false", (int)myRNA.getQuaternionPoolIndex(s,i)); } // And a study using the Runge Kutta Merson integrator bool suppressProject = false; RungeKuttaMersonIntegrator myStudy(mbs); //RungeKuttaFeldbergIntegrator myStudy(mbs); //RungeKutta3Integrator myStudy(mbs); //CPodesIntegrator myStudy(mbs); //VerletIntegrator myStudy(mbs); //ExplicitEulerIntegrator myStudy(mbs); myStudy.setAccuracy(1e-2); myStudy.setConstraintTolerance(1e-3); myStudy.setProjectEveryStep(false); Visualizer display(mbs); display.setBackgroundColor(White); display.setBackgroundType(Visualizer::SolidColor); display.setMode(Visualizer::RealTime); for (MobilizedBodyIndex i(1); i<myRNA.getNumBodies(); ++i) myRNA.decorateBody(i, display); myRNA.decorateGlobal(display); DecorativeLine rbProto; rbProto.setColor(Orange).setLineThickness(3); display.addRubberBandLine(GroundIndex, attachPt,MobilizedBodyIndex(myRNA.getNumBodies()-1),Vec3(0), rbProto); //display.addRubberBandLine(GroundIndex, -attachPt,myRNA.getNumBodies()-1,Vec3(0), rbProto); const Real dt = 1./30; // output intervals printf("time nextStepSize\n"); s.updTime() = 0; for (int i=0; i<50; ++i) saveEm.push_back(s); // delay display.report(s); myStudy.initialize(s); cout << "Using Integrator " << std::string(myStudy.getMethodName()) << ":\n"; cout << "ACCURACY IN USE=" << myStudy.getAccuracyInUse() << endl; cout << "CTOL IN USE=" << myStudy.getConstraintToleranceInUse() << endl; cout << "TIMESCALE=" << mbs.getDefaultTimeScale() << endl; cout << "U WEIGHTS=" << s.getUWeights() << endl; cout << "Z WEIGHTS=" << s.getZWeights() << endl; cout << "1/QTOLS=" << s.getQErrWeights() << endl; cout << "1/UTOLS=" << s.getUErrWeights() << endl; saveEm.push_back(myStudy.getState()); for (int i=0; i<50; ++i) saveEm.push_back(myStudy.getState()); // delay display.report(myStudy.getState()); const double startReal = realTime(), startCPU = cpuTime(); int stepNum = 0; for (;;) { const State& ss = myStudy.getState(); mbs.realize(ss); if ((stepNum++%100)==0) { printf("%5g qerr=%10.4g uerr=%10.4g hNext=%g\n", ss.getTime(), myRNA.getQErr(ss).normRMS(), myRNA.getUErr(ss).normRMS(), myStudy.getPredictedNextStepSize()); printf(" E=%14.8g (pe=%10.4g ke=%10.4g)\n", mbs.calcEnergy(ss), mbs.calcPotentialEnergy(ss), mbs.calcKineticEnergy(ss)); cout << "QERR=" << ss.getQErr() << endl; cout << "UERR=" << ss.getUErr() << endl; } //if (s.getTime() - std::floor(s.getTime()) < 0.2) // display.addEphemeralDecoration( DecorativeSphere(10).setColor(Green) ); display.report(ss); saveEm.push_back(ss); if (ss.getTime() >= 10) break; // TODO: should check for errors or have or teach RKM to throw. myStudy.stepTo(ss.getTime() + dt, Infinity); } printf("CPU time=%gs, REAL time=%gs\n", cpuTime()-startCPU, realTime()-startReal); printf("Using Integrator %s:\n", myStudy.getMethodName()); printf("# STEPS/ATTEMPTS = %d/%d\n", myStudy.getNumStepsTaken(), myStudy.getNumStepsAttempted()); printf("# ERR TEST FAILS = %d\n", myStudy.getNumErrorTestFailures()); printf("# CONVERGENCE FAILS = %d\n", myStudy.getNumConvergenceTestFailures()); printf("# REALIZE/PROJECT = %d/%d\n", myStudy.getNumRealizations(), myStudy.getNumProjections()); printf("# PROJECTION FAILS = %d\n", myStudy.getNumProjectionFailures()); display.dumpStats(std::cout); while(true) { for (int i=0; i < (int)saveEm.size(); ++i) { display.report(saveEm[i]); //display.report(saveEm[i]); // half speed } getchar(); } } catch (const exception& e) { printf("EXCEPTION THROWN: %s\n", e.what()); exit(1); } }
int main(int argc, char** argv) { try { // If anything goes wrong, an exception will be thrown. // CREATE MULTIBODY SYSTEM AND ITS SUBSYSTEMS MultibodySystem mbs; SimbodyMatterSubsystem matter(mbs); GeneralForceSubsystem forces(mbs); DecorationSubsystem viz(mbs); Force::UniformGravity gravity(forces, matter, Vec3(0, -g, 0)); // ADD BODIES AND THEIR MOBILIZERS Body::Rigid body = Body::Rigid(MassProperties(m, Vec3(0), m*UnitInertia::brick(hl[0],hl[1],hl[2]))); body.addDecoration(DecorativeBrick(hl).setOpacity(.5)); body.addDecoration(DecorativeLine(Vec3(0), Vec3(0,1,0)).setColor(Green)); MobilizedBody::Free mobilizedBody(matter.Ground(), Transform(), body, Transform()); MobilizedBody::Free mobilizedBody0(mobilizedBody, Transform(Vec3(1,2,0)), body, Transform(Vec3(0,1,0))); MobilizedBody::Free mobilizedBody2(mobilizedBody0, Vec3(-5,0,0), body, Transform()); Body::Rigid gear1body = Body::Rigid(MassProperties(m, Vec3(0), m*UnitInertia::cylinderAlongZ(.5, .1))); gear1body.addDecoration(DecorativeCircle(.5).setColor(Green).setOpacity(.7)); gear1body.addDecoration(DecorativeLine(Vec3(0), Vec3(.5,0,0)).setColor(Black).setLineThickness(4)); Body::Rigid gear2body = Body::Rigid(MassProperties(m, Vec3(0), m*UnitInertia::cylinderAlongZ(1.5, .1))); gear2body.addDecoration(Transform(), DecorativeCircle(1.5).setColor(Blue).setOpacity(.7)); gear2body.addDecoration(Transform(), DecorativeLine(Vec3(0), Vec3(1.5,0,0)).setColor(Black).setLineThickness(4)); MobilizedBody::Pin gear1(mobilizedBody2, Vec3(-1,0,0), gear1body, Transform()); // along z MobilizedBody::Pin gear2(mobilizedBody2, Vec3(1,0,0), gear2body, Transform()); // along z Constraint::NoSlip1D(mobilizedBody2, Vec3(-.5,0,0), UnitVec3(0,1,0), gear1, gear2); Constraint::ConstantSpeed(gear1, 100.); //Constraint::Ball myc2(matter.Ground(), Vec3(-4,2,0), mobilizedBody2, Vec3(0,1,0)); Constraint::Weld myc(matter.Ground(), Vec3(1,2,0), mobilizedBody, Vec3(0,1,0)); Constraint::Ball ball1(mobilizedBody, Vec3(2,0,0), mobilizedBody0, Vec3(3,1,1)); Constraint::Ball ball2(mobilizedBody0, Vec3(2,0,0), mobilizedBody2, Vec3(3,0,0)); //Constraint::PointInPlane pip(mobilizedBody0, UnitVec3(0,-1,0), 3, mobilizedBody2, Vec3(3,0,0)); //Constraint::ConstantOrientation ori(mobilizedBody, Rotation(), mobilizedBody0, Rotation()); //Constraint::ConstantOrientation ori2(mobilizedBody2, Rotation(), mobilizedBody0, Rotation()); //Constraint::Weld weld(mobilizedBody, Transform(Rotation(Pi/4, ZAxis), Vec3(1,1,0)), // mobilizedBody2, Transform(Rotation(-Pi/4, ZAxis), Vec3(-1,-1,0))); //MyConstraint xyz(gear1, 100.); viz.addBodyFixedDecoration(mobilizedBody, Transform(Vec3(1,2,3)), DecorativeText("hello world").setScale(.1)); /* class MyHandler : public ScheduledEventHandler { public: MyHandler(const Constraint& cons) : c(cons) { } Real getNextEventTime(const State&, bool includeCurrentTime) const { return .314; } void handleEvent(State& s, Real acc, const Vector& ywts, const Vector& cwts, Stage& modified, bool& shouldTerminate) const { cout << "<<<< TRIGGERED AT T=" << s.getTime() << endl; c.enable(s); modified = Stage::Model; } private: const Constraint& c; }; mbs.addEventHandler(new MyHandler(xyz)); */ State s = mbs.realizeTopology(); // returns a reference to the the default state //xyz.disable(s); //matter.setUseEulerAngles(s, true); mbs.realizeModel(s); // define appropriate states for this System //mobilizedBody0.setQ(s, .1); //mobilizedBody.setQ(s, .2); Visualizer display(mbs); display.setBackgroundColor(White); display.setBackgroundType(Visualizer::SolidColor); mbs.realize(s, Stage::Velocity); display.report(s); cout << "q=" << s.getQ() << endl; cout << "u=" << s.getU() << endl; cout << "qErr=" << s.getQErr() << endl; cout << "uErr=" << s.getUErr() << endl; for (ConstraintIndex cid(0); cid < matter.getNumConstraints(); ++cid) { const Constraint& c = matter.getConstraint(cid); int mp,mv,ma; c.getNumConstraintEquationsInUse(s, mp,mv,ma); cout << "CONSTRAINT " << cid << (c.isDisabled(s) ? "**DISABLED** " : "") << " constrained bodies=" << c.getNumConstrainedBodies(); if (c.getNumConstrainedBodies()) cout << " ancestor=" << c.getAncestorMobilizedBody().getMobilizedBodyIndex(); cout << " constrained mobilizers/nq/nu=" << c.getNumConstrainedMobilizers() << "/" << c.getNumConstrainedQ(s) << "/" << c.getNumConstrainedU(s) << " mp,mv,ma=" << mp << "," << mv << "," << ma << endl; for (ConstrainedBodyIndex cid(0); cid < c.getNumConstrainedBodies(); ++cid) { cout << " constrained body: " << c.getMobilizedBodyFromConstrainedBody(cid).getMobilizedBodyIndex(); cout << endl; } for (ConstrainedMobilizerIndex cmx(0); cmx < c.getNumConstrainedMobilizers(); ++cmx) { cout << " constrained mobilizer " << c.getMobilizedBodyFromConstrainedMobilizer(cmx).getMobilizedBodyIndex() << ", q(" << c.getNumConstrainedQ(s, cmx) << ")="; for (MobilizerQIndex i(0); i < c.getNumConstrainedQ(s, cmx); ++i) cout << " " << c.getConstrainedQIndex(s, cmx, i); cout << ", u(" << c.getNumConstrainedU(s, cmx) << ")="; for (MobilizerUIndex i(0); i < c.getNumConstrainedU(s, cmx); ++i) cout << " " << c.getConstrainedUIndex(s, cmx, i); cout << endl; } cout << c.getSubtree(); if (mp) { cout << "perr=" << c.getPositionErrorsAsVector(s) << endl; cout << " d(perrdot)/du=" << c.calcPositionConstraintMatrixP(s); cout << " ~d(Pt lambda)/dlambda=" << ~c.calcPositionConstraintMatrixPt(s); cout << " d(perr)/dq=" << c.calcPositionConstraintMatrixPNInv(s); Matrix P = c.calcPositionConstraintMatrixP(s); Matrix PQ(mp,matter.getNQ(s)); Vector out(matter.getNQ(s)); for (int i=0; i<mp; ++i) { Vector in = ~P[i]; matter.multiplyByNInv(s, true, in, out); PQ[i] = ~out; } cout << " calculated d(perr)/dq=" << PQ; } if (mv) { cout << "verr=" << c.getVelocityErrorsAsVector(s) << endl; //cout << " d(verrdot)/dudot=" << c.calcVelocityConstraintMatrixV(s); cout << " ~d(Vt lambda)/dlambda=" << ~c.calcVelocityConstraintMatrixVt(s); } } const Constraint& c = matter.getConstraint(myc.getConstraintIndex()); cout << "Default configuration shown. Ready? "; getchar(); mobilizedBody.setQToFitTransform (s, Transform(Rotation(.05,Vec3(1,1,1)),Vec3(.1,.2,.3))); mobilizedBody0.setQToFitTransform (s, Transform(Rotation(.05,Vec3(1,-1,1)),Vec3(.2,.2,.3))); mobilizedBody2.setQToFitTransform (s, Transform(Rotation(.05,Vec3(-1,1,1)),Vec3(.1,.2,.1))); mobilizedBody.setUToFitAngularVelocity(s, 10*Vec3(.1,.2,.3)); mobilizedBody0.setUToFitAngularVelocity(s, 10*Vec3(.1,.2,.3)); mobilizedBody2.setUToFitAngularVelocity(s, 10*Vec3(.1,.2,.3)); //gear1.setUToFitAngularVelocity(s, Vec3(0,0,500)); // these should be opposite directions! //gear2.setUToFitAngularVelocity(s, Vec3(0,0,100)); mbs.realize(s, Stage::Velocity); display.report(s); cout << "q=" << s.getQ() << endl; cout << "u=" << s.getU() << endl; cout << "qErr=" << s.getQErr() << endl; cout << "uErr=" << s.getUErr() << endl; cout << "p_MbM=" << mobilizedBody.getMobilizerTransform(s).p() << endl; cout << "v_MbM=" << mobilizedBody.getMobilizerVelocity(s)[1] << endl; cout << "Unassembled configuration shown. Ready to assemble? "; getchar(); // These are the SimTK Simmath integrators: RungeKuttaMersonIntegrator myStudy(mbs); //CPodesIntegrator myStudy(mbs, CPodes::BDF, CPodes::/*Newton*/Functional); //myStudy.setOrderLimit(2); // cpodes only //VerletIntegrator myStudy(mbs); // ExplicitEulerIntegrator myStudy(mbs, .0005); // fixed step //ExplicitEulerIntegrator myStudy(mbs); // variable step //myStudy.setMaximumStepSize(0.001); myStudy.setAccuracy(1e-6); myStudy.setAccuracy(1e-1); //myStudy.setProjectEveryStep(true); //myStudy.setProjectInterpolatedStates(false); myStudy.setConstraintTolerance(1e-7); myStudy.setConstraintTolerance(1e-2); //myStudy.setAllowInterpolation(false); //myStudy.setMaximumStepSize(.1); const Real dt = .02; // output intervals const Real finalTime = 2; myStudy.setFinalTime(finalTime); std::vector<State> saveEm; saveEm.reserve(2000); for (int i=0; i<50; ++i) saveEm.push_back(s); // delay // Peforms assembly if constraints are violated. myStudy.initialize(s); for (int i=0; i<50; ++i) saveEm.push_back(s); // delay cout << "Using Integrator " << std::string(myStudy.getMethodName()) << ":\n"; cout << "ACCURACY IN USE=" << myStudy.getAccuracyInUse() << endl; cout << "CTOL IN USE=" << myStudy.getConstraintToleranceInUse() << endl; cout << "TIMESCALE=" << mbs.getDefaultTimeScale() << endl; cout << "U WEIGHTS=" << s.getUWeights() << endl; cout << "Z WEIGHTS=" << s.getZWeights() << endl; cout << "1/QTOLS=" << s.getQErrWeights() << endl; cout << "1/UTOLS=" << s.getUErrWeights() << endl; { const State& s = myStudy.getState(); display.report(s); cout << "q=" << s.getQ() << endl; cout << "u=" << s.getU() << endl; cout << "qErr=" << s.getQErr() << endl; cout << "uErr=" << s.getUErr() << endl; cout << "p_MbM=" << mobilizedBody.getMobilizerTransform(s).p() << endl; cout << "PE=" << mbs.calcPotentialEnergy(s) << " KE=" << mbs.calcKineticEnergy(s) << " E=" << mbs.calcEnergy(s) << endl; cout << "angle=" << std::acos(~mobilizedBody.expressVectorInGroundFrame(s, Vec3(0,1,0)) * UnitVec3(1,1,1)) << endl; cout << "Assembled configuration shown. Ready to simulate? "; getchar(); } Integrator::SuccessfulStepStatus status; int nextReport = 0; mbs.resetAllCountersToZero(); int stepNum = 0; while ((status=myStudy.stepTo(nextReport*dt)) != Integrator::EndOfSimulation) { const State& s = myStudy.getState(); mbs.realize(s, Stage::Acceleration); if ((stepNum++%10)==0) { const Real angle = std::acos(~mobilizedBody.expressVectorInGroundFrame(s, Vec3(0,1,0)) * UnitVec3(1,1,1)); printf("%5g %10.4g E=%10.8g h%3d=%g %s%s\n", s.getTime(), angle, mbs.calcEnergy(s), myStudy.getNumStepsTaken(), myStudy.getPreviousStepSizeTaken(), Integrator::getSuccessfulStepStatusString(status).c_str(), myStudy.isStateInterpolated()?" (INTERP)":""); printf(" qerr=%10.8g uerr=%10.8g uderr=%10.8g\n", matter.getQErr(s).normRMS(), matter.getUErr(s).normRMS(), s.getSystemStage() >= Stage::Acceleration ? matter.getUDotErr(s).normRMS() : Real(-1)); #ifdef HASC cout << "CONSTRAINT perr=" << c.getPositionError(s) << " verr=" << c.getVelocityError(s) << " aerr=" << c.getAccelerationError(s) << endl; #endif //cout << " d(perrdot)/du=" << c.calcPositionConstraintMatrixP(s); //cout << " ~d(f)/d lambda=" << c.calcPositionConstraintMatrixPT(s); //cout << " d(perr)/dq=" << c.calcPositionConstraintMatrixPQInverse(s); cout << "Q=" << matter.getQ(s) << endl; cout << "U=" << matter.getU(s) << endl; cout << "Multipliers=" << matter.getMultipliers(s) << endl; } Vector qdot; matter.calcQDot(s, s.getU(), qdot); // cout << "===> qdot =" << qdot << endl; Vector qdot2; matter.multiplyByN(s, false, s.getU(), qdot2); // cout << "===> qdot2=" << qdot2 << endl; Vector u1,u2; matter.multiplyByNInv(s, false, qdot, u1); matter.multiplyByNInv(s, false, qdot2, u2); // cout << "===> u =" << s.getU() << endl; // cout << "===> u1=" << u1 << endl; // cout << "===> u2=" << u2 << endl; // cout << " norm=" << (s.getU()-u2).normRMS() << endl; display.report(s); saveEm.push_back(s); if (status == Integrator::ReachedReportTime) ++nextReport; } printf("Using Integrator %s:\n", myStudy.getMethodName()); printf("# STEPS/ATTEMPTS = %d/%d\n", myStudy.getNumStepsTaken(), myStudy.getNumStepsAttempted()); printf("# ERR TEST FAILS = %d\n", myStudy.getNumErrorTestFailures()); printf("# REALIZE/PROJECT = %d/%d\n", myStudy.getNumRealizations(), myStudy.getNumProjections()); printf("System stats: realize %dP %dV %dA, projectQ %d, projectU %d\n", mbs.getNumRealizationsOfThisStage(Stage::Position), mbs.getNumRealizationsOfThisStage(Stage::Velocity), mbs.getNumRealizationsOfThisStage(Stage::Acceleration), mbs.getNumProjectQCalls(), mbs.getNumProjectUCalls()); while(true) { for (int i=0; i < (int)saveEm.size(); ++i) { display.report(saveEm[i]); //display.report(saveEm[i]); // half speed } getchar(); } } catch (const exception& e) { printf("EXCEPTION THROWN: %s\n", e.what()); exit(1); } catch (...) { printf("UNKNOWN EXCEPTION THROWN\n"); exit(1); } }
void testConservationOfEnergy() { // Create the system. MultibodySystem system; SimbodyMatterSubsystem matter(system); GeneralForceSubsystem forces(system); Force::UniformGravity gravity(forces, matter, Vec3(0, -9.8, 0)); const Real Mass = 1; const Vec3 HalfShape = Vec3(1,.5,.25)/2; const Transform BodyAttach(Rotation(), Vec3(HalfShape[0],0,0)); Body::Rigid brickBody(MassProperties(Mass, Vec3(.1,.2,.3), Mass*Inertia(1,1.1,1.2,0.01,0.02,0.03))); //Body::Rigid brickBody(MassProperties(Mass, Vec3(0), // Mass*UnitInertia::ellipsoid(HalfShape))); brickBody.addDecoration(Transform(), DecorativeEllipsoid(HalfShape) .setOpacity(0.25) .setColor(Blue)); brickBody.addDecoration(BodyAttach, DecorativeFrame(0.5).setColor(Red)); const int NBod=50; MobilizedBody::Free brick1(matter.Ground(), Transform(), brickBody, BodyAttach); MobilizedBody::Free brick2(brick1, Transform(), brickBody, BodyAttach); MobilizedBody prev=brick2; MobilizedBody body25; for (int i=0; i<NBod; ++i) { MobilizedBody::Ball next(prev, -1*BodyAttach.p(), brickBody, BodyAttach); if (i==25) body25=next; //Force::TwoPointLinearSpring(forces, // prev, Vec3(0), next, Vec3(0), 1000, 1); prev=next; } Constraint::Ball(matter.Ground(), Vec3(0,1,0)-2*NBod/3*BodyAttach.p(), prev, BodyAttach.p()); Constraint::Ball(matter.Ground(), Vec3(0,1,0)-1*NBod/3*BodyAttach.p(), body25, BodyAttach.p()); Vec6 k1(1,100,1,100,100,100), c1(0); Force::LinearBushing(forces, matter.Ground(), -2*NBod/3*BodyAttach.p(), prev, BodyAttach.p(), k1, c1); matter.Ground().addBodyDecoration(-2*NBod/3*BodyAttach.p(), DecorativeFrame().setColor(Green)); Force::Thermostat thermo(forces, matter, SimTK_BOLTZMANN_CONSTANT_MD, 5000, .1); Vec6 k(1,100,1,100,100,100), c(0); Force::LinearBushing bushing1(forces, matter.Ground(), -1*NBod/3*BodyAttach.p(), brick1, BodyAttach, k, c); Force::LinearBushing bushing2(forces, brick1, Transform(), brick2, BodyAttach, k, c); matter.Ground().addBodyDecoration(-1*NBod/3*BodyAttach.p(), DecorativeFrame().setColor(Green)); Visualizer viz(system); Visualizer::Reporter* reporter = new Visualizer::Reporter(viz, 1./30); viz.setBackgroundType(Visualizer::SolidColor); system.addEventReporter(reporter); ThermoReporter* thermoReport = new ThermoReporter (system, thermo, bushing1, bushing2, 1./10); system.addEventReporter(thermoReport); // Initialize the system and state. system.realizeTopology(); State state = system.getDefaultState(); viz.report(state); printf("Default state -- hit ENTER\n"); cout << "t=" << state.getTime() << " q=" << brick1.getQAsVector(state) << brick2.getQAsVector(state) << " u=" << brick1.getUAsVector(state) << brick2.getUAsVector(state) << "\nnChains=" << thermo.getNumChains(state) << " T=" << thermo.getBathTemperature(state) << "\nt_relax=" << thermo.getRelaxationTime(state) << " kB=" << thermo.getBoltzmannsConstant() << endl; getchar(); state.setTime(0); system.realize(state, Stage::Acceleration); Vector initU(state.getNU()); initU = Test::randVector(state.getNU()); state.updU()=initU; RungeKuttaMersonIntegrator integ(system); //integ.setMinimumStepSize(1e-1); integ.setAccuracy(1e-2); TimeStepper ts(system, integ); ts.initialize(state); const State& istate = integ.getState(); viz.report(integ.getState()); viz.zoomCameraToShowAllGeometry(); printf("After initialize -- hit ENTER\n"); cout << "t=" << integ.getTime() << "\nE=" << system.calcEnergy(istate) << "\nEbath=" << thermo.calcBathEnergy(istate) << endl; thermoReport->handleEvent(istate); getchar(); // Simulate it. ts.stepTo(20.0); viz.report(integ.getState()); viz.zoomCameraToShowAllGeometry(); printf("After simulation:\n"); cout << "t=" << integ.getTime() << "\nE=" << system.calcEnergy(istate) << "\nEbath=" << thermo.calcBathEnergy(istate) << "\nNsteps=" << integ.getNumStepsTaken() << endl; thermoReport->handleEvent(istate); }
int main(int argc, char** argv) { try { // If anything goes wrong, an exception will be thrown. MultibodySystem mbs; mbs.setUseUniformBackground(true); GeneralForceSubsystem forces(mbs); SimbodyMatterSubsystem pend(mbs); DecorationSubsystem viz(mbs); Force::UniformGravity gravity(forces, pend, Vec3(0, -g, 0)); MobilizedBody::Ball connector(pend.Ground(), Transform(1*Vec3(0, 0, 0)), MassProperties(1, Vec3(0,0,0), Inertia(10,20,30)), Transform(1*Vec3(0, .5, 0))); connector.setDefaultRadius(0.05); // for the artwork //connector.setDefaultRotation( Rotation(Pi/4, Vec3(0,0,1) ); const Real m1 = 5; const Real m2 = 1; const Real radiusRatio = std::pow(m2/m1, 1./3.); const Vec3 weight1Location(0, 0, -d/2); // in local frame of swinging body const Vec3 weight2Location(0, 0, d/2); // in local frame of swinging body const Vec3 COM = (m1*weight1Location+m2*weight2Location)/(m1+m2); const MassProperties swingerMassProps (m1+m2, COM, 1*Inertia(1,1,1) + m1*UnitInertia::pointMassAt(weight1Location) + m2*UnitInertia::pointMassAt(weight2Location)); MobilizedBody::Screw swinger(connector, Transform( Rotation( 0*.7, Vec3(9,8,7) ), 1*Vec3(0,-.5,0)), swingerMassProps, Transform( Rotation(0*1.3, Vec3(0,0,1) ), COM+0*Vec3(0,0,3)), // inboard joint location 0.3); // pitch // Add a blue sphere around the weight. viz.addBodyFixedDecoration(swinger, weight1Location, DecorativeSphere(d/8).setColor(Blue).setOpacity(.2)); viz.addBodyFixedDecoration(swinger, weight2Location, DecorativeSphere(radiusRatio*d/8).setColor(Green).setOpacity(.2)); viz.addRubberBandLine(GroundIndex, Vec3(0), swinger, Vec3(0), DecorativeLine().setColor(Blue).setLineThickness(10) .setRepresentation(DecorativeGeometry::DrawPoints)); //forces.addMobilityConstantForce(swinger, 0, 10); Force::ConstantTorque(forces, swinger, Vec3(0,0,10)); //forces.addConstantForce(swinger, Vec3(0), Vec3(0,10,0)); //forces.addConstantForce(swinger, Vec3(0,0,0), Vec3(10,10,0)); // z should do nothing //forces.addMobilityConstantForce(swinger, 1, 10); // forces.addMobilityConstantForce(swinger, 2, 60-1.2); State s = mbs.realizeTopology(); // define appropriate states for this System pend.setUseEulerAngles(s, true); mbs.realizeModel(s); mbs.realize(s); // Create a study using the Runge Kutta Merson integrator RungeKuttaMersonIntegrator myStudy(mbs); myStudy.setAccuracy(1e-6); // This will pick up decorative geometry from // each subsystem that generates any, including of course the // DecorationSubsystem, but not limited to it. Visualizer display(mbs); const Real expectedPeriod = 2*Pi*std::sqrt(d/g); printf("Expected period: %g seconds\n", expectedPeriod); const Real dt = 1./30; // output intervals const Real finalTime = 1*expectedPeriod; for (Real startAngle = 10; startAngle <= 90; startAngle += 10) { s = mbs.getDefaultState(); connector.setQToFitRotation(s, Rotation(Pi/4, Vec3(1,1,1)) ); printf("time theta energy *************\n"); swinger.setQToFitTransform(s, Transform( Rotation( BodyRotationSequence, 0*Pi/2, XAxis, 0*Pi/2, YAxis ), Vec3(0,0,0) )); swinger.setUToFitVelocity(s, SpatialVec(0*Vec3(1.1,1.2,1.3),Vec3(0,0,-1))); s.updTime() = 0; myStudy.initialize(s); cout << "MassProperties in B=" << swinger.expressMassPropertiesInAnotherBodyFrame(myStudy.getState(),swinger); cout << "MassProperties in G=" << swinger.expressMassPropertiesInGroundFrame(myStudy.getState()); cout << "Spatial Inertia =" << swinger.calcBodySpatialInertiaMatrixInGround(myStudy.getState()); int stepNum = 0; for (;;) { // Should check for errors and other interesting status returns. myStudy.stepTo(myStudy.getTime() + dt); const State& s = myStudy.getState(); // s is now the integrator's internal state if ((stepNum++%10)==0) { // This is so we can calculate potential energy (although logically // one should be able to do that at Stage::Position). mbs.realize(s, Stage::Dynamics); cout << s.getTime() << ": E=" << mbs.calcEnergy(s) << " connector q=" << connector.getQ(s) << ": swinger q=" << swinger.getQ(s) << endl; // This is so we can look at the UDots. mbs.realize(s, Stage::Acceleration); cout << "q =" << pend.getQ(s) << endl; cout << "u =" << pend.getU(s) << endl; cout << "ud=" << pend.getUDot(s) << endl; cout << "Connector V=" << connector.getMobilizerVelocity(s) << endl; cout << "Swinger V=" << swinger.getMobilizerVelocity(s) << endl; const Rotation& R_MbM = swinger.getMobilizerTransform(s).R(); Vec4 aaMb = R_MbM.convertRotationToAngleAxis(); cout << "angle=" << aaMb[0] << endl; cout << "axisMb=" << aaMb.drop1(0) << endl; cout << "axisMb=" << ~R_MbM*aaMb.drop1(0) << endl; } display.report(s); if (s.getTime() >= finalTime) break; } } } catch (const exception& e) { printf("EXCEPTION THROWN: %s\n", e.what()); exit(1); } }
int main(int argc, char** argv) { try { // If anything goes wrong, an exception will be thrown. // CREATE MULTIBODY SYSTEM AND ITS SUBSYSTEMS MultibodySystem mbs; mbs.setUseUniformBackground(true); SimbodyMatterSubsystem crankRocker(mbs); GeneralForceSubsystem forces(mbs); DecorationSubsystem viz(mbs); Force::UniformGravity gravity(forces, crankRocker, Vec3(0, -g, 0)); // ADD BODIES AND THEIR MOBILIZERS Body::Rigid crankBody = Body::Rigid(MassProperties(.1, Vec3(0), 0.1*UnitInertia::brick(1,3,.5))); crankBody.addDecoration(DecorativeEllipsoid(0.1*Vec3(1,3,.4)) .setResolution(10) .setOpacity(.2)); Body::Rigid sliderBody = Body::Rigid(MassProperties(.2, Vec3(0), 0.2*UnitInertia::brick(1,5,.5))); sliderBody.addDecoration(DecorativeEllipsoid(0.2*Vec3(1,5,.4)) .setColor(Blue) .setResolution(10) .setOpacity(.2)); Body::Rigid longBar = Body::Rigid(MassProperties(0.01, Vec3(0), 0.01*UnitInertia::cylinderAlongX(.1, 5))); longBar.addDecoration(Rotation(Pi/2,ZAxis), DecorativeCylinder(.01, 1)); MobilizedBody::Pin crank(crankRocker.Ground(), Transform(), crankBody, Transform(Vec3(0, .15, 0))); MobilizedBody::Pin slider(crankRocker.Ground(), Transform(Vec3(2.5,0,0)), sliderBody, Transform(Vec3(0, 1, 0))); MobilizedBody::Universal rightConn(crank, Transform(Rotation(-Pi/2,YAxis),Vec3(0,-.3,0)), longBar, Transform(Rotation(-Pi/2,YAxis),Vec3(-1,0,0))); Constraint::Ball ball(slider, Vec3(0,-1, 0), rightConn, Vec3(1,0,0)); ball.setDefaultRadius(0.01); //Constraint::Rod rodl(leftConn, Vec3(0), rightConn, Vec3(-2.5,0,0), 2.5); //Constraint::Rod rodr(leftConn, Vec3(2.5,-1,0), rightConn, Vec3(-1.5,0,0), std::sqrt(2.)); //Constraint::Rod rodo(leftConn, Vec3(1.5,0,0), rightConn, Vec3(-2.5,1,0), std::sqrt(2.)); //Constraint::Rod rodl(leftConn, Vec3(-2.5,0,0), rightConn, Vec3(-2.5,0,0), 5); //Constraint::Rod rodr(leftConn, Vec3(2.5,0,0), rightConn, Vec3(2.5,0,0), 5); //Constraint::Rod rodo(leftConn, Vec3(2.5,-1,0), rightConn, Vec3(-2.5,1,0), 2); // Add visualization line (orange=spring, black=constraint) //viz.addRubberBandLine(crank, Vec3(0,-3,0), // slider, Vec3(0,-5,0), // DecorativeLine().setColor(Black).setLineThickness(4)); //forces.addMobilityConstantForce(leftPendulum, 0, 20); //forces.addCustomForce(ShermsForce(leftPendulum,rightPendulum)); //forces.addGlobalEnergyDrain(1); Force::MobilityConstantForce(forces, crank, 0, 1); Force::MobilityLinearDamper(forces, crank, 0, 1.0); //Motion::Linear(crank, Vec3(a,b,c)); // crank(t)=at^2+bt+c //Motion::Linear lmot(rightConn, Vec3(a,b,c)); // both axes follow //lmot.setAxis(1, Vec3(d,e,f)); //Motion::Orientation(someBall, orientFuncOfT); //someBall.prescribeOrientation(orientFunc); //Motion::Relax(crank); // acc=vel=0, pos determined by some default relaxation solver // Like this, or should this be an Instance-stage mode of every mobilizer? //Motion::Lock(crank); // acc=vel=0; pos is discrete or fast //Motion::Steady(crank, Vec3(1,2,3)); // acc=0; vel=constant; pos integrated //Motion::Steady crankRate(crank, 1); // acc=0; vel=constant, same for each axis; pos integrated // or ... //crank.lock(state); //crank.setMotionType(state, Regular|Discrete|Fast|Prescribed, stage); // need a way to register a mobilizer with a particular relaxation solver, // switch between dynamic, continuous relaxed, end-of-step relaxed, discrete. // what about a "local" (explicit) relaxation, like q=(q1+q2)/2 ? State s = mbs.realizeTopology(); // returns a reference to the the default state mbs.realizeModel(s); // define appropriate states for this System //crankRate.setRate(s, 3); crank.setAngle(s, 5); //q crank.setRate(s, 3); //u Visualizer display(mbs); mbs.realize(s, Stage::Position); display.report(s); cout << "q=" << s.getQ() << endl; cout << "qErr=" << s.getQErr() << endl; crank.setAngle(s, -30*Deg2Rad); //crank.setQToFitRotation (s, Rotation::aboutZ(-.9*Pi/2)); //TODO //rightPendulum.setUToFitLinearVelocity(s, Vec3(1.1,0,1.2)); //crank.setUToFitAngularVelocity(s, 10*Vec3(.1,.2,.3)); mbs.realize(s, Stage::Velocity); display.report(s); cout << "q=" << s.getQ() << endl; cout << "qErr=" << s.getQErr() << endl; // These are the SimTK Simmath integrators: RungeKuttaMersonIntegrator myStudy(mbs); //CPodesIntegrator myStudy(mbs, CPodes::BDF, CPodes::Newton); //myStudy.setMaximumStepSize(0.001); myStudy.setAccuracy(1e-3); //myStudy.setProjectEveryStep(true); //myStudy.setAllowInterpolation(false); //myStudy.setMaximumStepSize(.1); const Real dt = 1./30; // output intervals const Real finalTime = 10; myStudy.setFinalTime(finalTime); cout << "Hit ENTER in console to continue ...\n"; getchar(); display.report(s); cout << "Hit ENTER in console to continue ...\n"; getchar(); // Peforms assembly if constraints are violated. myStudy.initialize(s); myStudy.setProjectEveryStep(false); myStudy.setConstraintTolerance(.001); myStudy.initialize(myStudy.getState()); cout << "Using Integrator " << std::string(myStudy.getMethodName()) << ":\n"; cout << "ACCURACY IN USE=" << myStudy.getAccuracyInUse() << endl; cout << "CTOL IN USE=" << myStudy.getConstraintToleranceInUse() << endl; cout << "TIMESCALE=" << mbs.getDefaultTimeScale() << endl; cout << "U WEIGHTS=" << s.getUWeights() << endl; cout << "Z WEIGHTS=" << s.getZWeights() << endl; cout << "1/QTOLS=" << s.getQErrWeights() << endl; cout << "1/UTOLS=" << s.getUErrWeights() << endl; { const State& s = myStudy.getState(); display.report(s); cout << "q=" << s.getQ() << endl; cout << "qErr=" << s.getQErr() << endl; } Integrator::SuccessfulStepStatus status; int nextReport = 0; while ((status=myStudy.stepTo(nextReport*dt, Infinity)) != Integrator::EndOfSimulation) { const State& s = myStudy.getState(); mbs.realize(s); const Real crankAngle = crank.getBodyRotation(s).convertRotationToAngleAxis()[0] * Rad2Deg; printf("%5g %10.4g E=%10.8g h%3d=%g %s%s\n", s.getTime(), crankAngle, mbs.calcEnergy(s), myStudy.getNumStepsTaken(), myStudy.getPreviousStepSizeTaken(), Integrator::getSuccessfulStepStatusString(status).c_str(), myStudy.isStateInterpolated()?" (INTERP)":""); printf(" qerr=%10.8g uerr=%10.8g uderr=%10.8g\n", crankRocker.getQErr(s).normRMS(), crankRocker.getUErr(s).normRMS(), crankRocker.getUDotErr(s).normRMS()); display.report(s); if (status == Integrator::ReachedReportTime) ++nextReport; } for (int i=0; i<100; ++i) display.report(myStudy.getState()); printf("Using Integrator %s:\n", myStudy.getMethodName()); printf("# STEPS/ATTEMPTS = %d/%d\n", myStudy.getNumStepsTaken(), myStudy.getNumStepsAttempted()); printf("# ERR TEST FAILS = %d\n", myStudy.getNumErrorTestFailures()); printf("# REALIZE/PROJECT = %d/%d\n", myStudy.getNumRealizations(), myStudy.getNumProjections()); } catch (const exception& e) { printf("EXCEPTION THROWN: %s\n", e.what()); exit(1); } catch (...) { printf("UNKNOWN EXCEPTION THROWN\n"); exit(1); } }
void testPrescribedMotion2() { // Create a system prescribing the motion of two Qs. MultibodySystem system; SimbodyMatterSubsystem matter(system); createCylinderSystem(system); MobilizedBodyIndex body1 = MobilizedBodyIndex(2); MobilizerQIndex coordinate1 = MobilizerQIndex(1); Vector coefficients1(2); coefficients1[0] = 0.1; coefficients1[1] = 0.0; Function* function1 = new Function::Linear(coefficients1); Constraint::PrescribedMotion constraint1(matter, function1, body1, coordinate1); MobilizedBodyIndex body2 = MobilizedBodyIndex(2); MobilizerQIndex coordinate2 = MobilizerQIndex(0); Vector coefficients2(3); coefficients2[0] = 0.5; coefficients2[1] = -0.2; coefficients2[2] = 1.1; Function* function2 = new Function::Polynomial(coefficients2); Constraint::PrescribedMotion constraint2(matter, function2, body2, coordinate2); // Must track work done by the constraints in order to check that // energy is conserved. Measure::Zero zeroMeas(matter); PowerMeasure<Real> powMeas1(matter, constraint1); Measure::Integrate workMeas1(matter, powMeas1, zeroMeas); PowerMeasure<Real> powMeas2(matter, constraint2); Measure::Integrate workMeas2(matter, powMeas2, zeroMeas); State state; createState(system, state); workMeas1.setValue(state, 0); // override createState workMeas2.setValue(state, 0); // override createState // Make sure the constraint is satisfied. Vector args(1, state.getTime()); SimTK_TEST_EQ(function1->calcValue(args), matter.getMobilizedBody(body1).getOneQ(state, coordinate1)); SimTK_TEST_EQ(function2->calcValue(args), matter.getMobilizedBody(body2).getOneQ(state, coordinate2)); // Simulate it and make sure the constraint is working correctly and energy is being conserved. const Real energy0 = system.calcEnergy(state); RungeKuttaMersonIntegrator integ(system); integ.setReturnEveryInternalStep(true); integ.initialize(state); while (integ.getTime() < 10.0) { integ.stepTo(10.0); const State& istate = integ.getState(); system.realize(istate, Stage::Acceleration); const Real energy = system.calcEnergy(istate); const Real power1 = powMeas1.getValue(istate); const Real work1 = workMeas1.getValue(istate); const Real power2 = powMeas2.getValue(istate); const Real work2 = workMeas2.getValue(istate); Vector args(1, istate.getTime()); SimTK_TEST_EQ_TOL(function1->calcValue(args), matter.getMobilizedBody(body1).getOneQ(istate, coordinate1), integ.getConstraintToleranceInUse()); SimTK_TEST_EQ_TOL(function2->calcValue(args), matter.getMobilizedBody(body2).getOneQ(istate, coordinate2), integ.getConstraintToleranceInUse()); // Energy conservation depends on global integration accuracy; // accuracy returned here is local so we'll fudge at 10X. const Real etol = 10*integ.getAccuracyInUse() *std::max(std::abs(energy-(work1+work2)), std::abs(energy0)); SimTK_TEST_EQ_TOL(energy0, energy-(work1+work2), etol) } }
void testSpeedCoupler3() { // Create a system with a constraint that uses both u's and q's. // This will not be workless in general. MultibodySystem system; SimbodyMatterSubsystem matter(system); createCylinderSystem(system); MobilizedBody& first = matter.updMobilizedBody(MobilizedBodyIndex(1)); std::vector<MobilizedBodyIndex> ubody(2), qbody(1); std::vector<MobilizerUIndex> uindex(2); std::vector<MobilizerQIndex> qindex(1); ubody[0] = MobilizedBodyIndex(1); ubody[1] = MobilizedBodyIndex(3); qbody[0] = MobilizedBodyIndex(5); uindex[0] = MobilizerUIndex(0); uindex[1] = MobilizerUIndex(1); qindex[0] = MobilizerQIndex(1); Function* function = new CompoundFunction(); Constraint::SpeedCoupler coupler(matter, function, ubody, uindex, qbody, qindex); PowerMeasure<Real> powMeas(matter, coupler); Measure::Zero zeroMeas(matter); Measure::Integrate workMeas(matter, powMeas, zeroMeas); State state; createState(system, state); workMeas.setValue(state, 0); // override createState // Make sure the constraint is satisfied. Vector args(function->getArgumentSize()); args[0] = matter.getMobilizedBody(ubody[0]).getOneU(state, uindex[0]); args[1] = matter.getMobilizedBody(ubody[1]).getOneU(state, uindex[1]); args[2] = matter.getMobilizedBody(qbody[0]).getOneQ(state, qindex[0]); SimTK_TEST_EQ(0.0, function->calcValue(args)); // Simulate it and make sure the constraint is working correctly. // We don't expect energy to be conserved here but energy minus the // work done by the constraint should be conserved. Real energy0 = system.calcEnergy(state); RungeKuttaMersonIntegrator integ(system); integ.setAccuracy(1e-6); integ.setReturnEveryInternalStep(true); integ.initialize(state); while (integ.getTime() < 10.0) { integ.stepTo(10.0); const State& istate = integ.getState(); system.realize(istate, Stage::Acceleration); const Real energy = system.calcEnergy(istate); const Real power = powMeas.getValue(istate); const Real work = workMeas.getValue(istate); args[0] = matter.getMobilizedBody(ubody[0]).getOneU(state, uindex[0]); args[1] = matter.getMobilizedBody(ubody[1]).getOneU(state, uindex[1]); args[2] = matter.getMobilizedBody(qbody[0]).getOneQ(state, qindex[0]); SimTK_TEST_EQ_TOL(0.0, function->calcValue(args), integ.getConstraintToleranceInUse()); // Energy conservation depends on global integration accuracy; // accuracy returned here is local so we'll fudge at 10X. const Real etol = 10*integ.getAccuracyInUse() *std::max(std::abs(energy-work), std::abs(energy0)); SimTK_TEST_EQ_TOL(energy0, energy-work, etol) } }
void testCoordinateCoupler2() { // Create a system involving a constraint that affects multiple mobilizers. MultibodySystem system; SimbodyMatterSubsystem matter(system); createCylinderSystem(system); MobilizedBody& first = matter.updMobilizedBody(MobilizedBodyIndex(1)); std::vector<MobilizedBodyIndex> mobilizers(3); std::vector<MobilizerQIndex> coordinates(3); mobilizers[0] = MobilizedBodyIndex(1); mobilizers[1] = MobilizedBodyIndex(1); mobilizers[2] = MobilizedBodyIndex(5); coordinates[0] = MobilizerQIndex(0); coordinates[1] = MobilizerQIndex(1); coordinates[2] = MobilizerQIndex(1); Function* function = new CompoundFunction(); Constraint::CoordinateCoupler coupler(matter, function, mobilizers, coordinates); State state; createState(system, state); // Make sure the constraint is satisfied. Vector cq(function->getArgumentSize()); for (int i = 0; i < cq.size(); ++i) cq[i] = matter.getMobilizedBody(mobilizers[i]) .getOneQ(state, coordinates[i]); SimTK_TEST_EQ(0.0, function->calcValue(cq)); // Simulate it and make sure the constraint is working correctly and // energy is being conserved. This is a workless constraint so the // power should be zer system.realize(state, Stage::Acceleration); Real energy0 = system.calcEnergy(state); RungeKuttaMersonIntegrator integ(system); integ.setReturnEveryInternalStep(true); integ.initialize(state); while (integ.getTime() < 10.0) { integ.stepTo(10.0); const State& istate = integ.getState(); system.realize(istate, Stage::Acceleration); const Vector& u = istate.getU(); const Real energy = system.calcEnergy(istate); const Real power = coupler.calcPower(istate); for (int i = 0; i < cq.size(); ++i) cq[i] = matter.getMobilizedBody(mobilizers[i]) .getOneQ(istate, coordinates[i]); SimTK_TEST_EQ_TOL(0.0, function->calcValue(cq), integ.getConstraintToleranceInUse()); // Power output should always be zero to machine precision // with some slop for calculation of multipliers. SimTK_TEST_EQ_SIZE(0.0, power, istate.getNU()); // Energy conservation depends on global integration accuracy; // accuracy returned here is local so we'll fudge at 10X. const Real etol = 10*integ.getAccuracyInUse() *std::max(std::abs(energy), std::abs(energy0)); SimTK_TEST_EQ_TOL(energy0, energy, etol); } }