//============================================================================== // MAIN //============================================================================== // Simulate forever with a maximum step size small enough to provide adequate // polling for user input and screen updating. int main() { try { // catch errors if any // Create the Simbody MultibodySystem and Visualizer. MyMechanism mech; // We want real time performance here and don't need high accuracy, so we'll // use semi explicit Euler. However, we hope to take fairly large steps so // need error control to avoid instability. We must also prevent // interpolation so that the state returned after each step is the // integrator's "advanced state", which is modifiable, so that we can update // it in response to user input. SemiExplicitEuler2Integrator integ(mech.getSystem()); integ.setAccuracy(Real(1e-1)); // 10% integ.setAllowInterpolation(false); integ.initialize(mech.getDefaultState()); unsigned stepNum = 0; while (true) { // Get access to State being advanced by the integrator. Interpolation // must be off so that we're modifying the actual trajectory. State& state = integ.updAdvancedState(); // Output a frame to the Visualizer if it is time. if (stepNum % DrawEveryN == 0) mech.draw(state); // Check for user input periodically. if (stepNum % PollUserEveryN == 0 && mech.processUserInput(state)) break; // stop if user picked Quit from the Run menu // Advance time by MaxStepSize. Might take multiple internal steps to // get there, depending on difficulty and required accuracy. integ.stepBy(MaxStepSize); ++stepNum; } // DONE. dumpIntegratorStats(integ); } catch (const std::exception& e) { std::cout << "ERROR: " << e.what() << std::endl; return 1; } return 0; }
//============================================================================== // MAIN //============================================================================== // Simulate forever with a small max step size. int main() { try { // catch errors if any // Create the Simbody MultibodySystem and Visualizer. MyMechanism mech; // We're forcing very small step sizes so should use very low order // integration and loose accuracy. We must prevent interpolation so that the // state returned after each step is the integrator's "advanced state", // which is modifiable, in case we need to make a state change. SemiExplicitEuler2Integrator integ(mech.getSystem()); integ.setAccuracy(Real(1e-1)); // 10% integ.setAllowInterpolation(false); integ.initialize(mech.getDefaultState()); unsigned stepNum = 0; while (true) { // Get access to State being advanced by the integrator. Interpolation // must be off so that we're modifying the actual trajectory. State& state = integ.updAdvancedState(); // Output a frame to the Visualizer if it is time. if (stepNum % DrawEveryN == 0) mech.draw(state); // Check for user input periodically. if (stepNum % PollUserEveryN == 0 && mech.processUserInput(state)) break; // stop if user picked Quit from the Run menu // Check for speed/torque control transition events and handle. const Real trqNow = mech.getMotorTorque(state); if (mech.isSpeedControlEnabled(state)) { if (std::abs(trqNow) > mech.getTorqueLimit(state)) { printf("\n%d: SWITCH TO TORQUE CONTROL cuz trqNow=%g\n", stepNum, trqNow); mech.switchToTorqueControl(state); } } else { // Currently limiting torque. // If the torque is now in the same direction as the error, try // to switch back to speed control. If that doesn't work we'll at // least reverse the applied maximum torque. const Real errNow = mech.getSpeedError(state); if (errNow * trqNow > 0) { printf("\n%d: TRY SPEED CONTROL cuz errNow=%g, trqNow=%g\n", stepNum, errNow, trqNow); mech.tryToSwitchToSpeedControl(state); } } // Advance time by MaxStepSize. Might take multiple internal steps to // get there, depending on required accuracy. integ.stepBy(MaxStepSize); ++stepNum; } // DONE. dumpIntegratorStats(integ); } catch (const std::exception& e) { std::cout << "ERROR: " << e.what() << std::endl; return 1; } return 0; }