From d2fb8067167785b299482d247aaf90a35f55b62c Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 28 Jan 2013 16:15:50 +0100 Subject: LocomotorPrimitives: Switch to using Logger class for logging --- LocomotorPrimitives.cpp | 62 +++++++++++++++++++++------------------ LocomotorPrimitivesController.cpp | 14 ++++----- LocomotorPrimitivesController.h | 2 ++ Logger.cpp | 58 ++++++++++++++++++++++++++++++++++++ Logger.h | 42 ++++++++++++++++++++++++++ 5 files changed, 141 insertions(+), 37 deletions(-) create mode 100644 Logger.cpp create mode 100644 Logger.h diff --git a/LocomotorPrimitives.cpp b/LocomotorPrimitives.cpp index 3bb8d97..e5ff7f6 100644 --- a/LocomotorPrimitives.cpp +++ b/LocomotorPrimitives.cpp @@ -11,23 +11,25 @@ #include "LocomotorPrimitivesManager.h" #include "LocomotorPrimitivesController.h" +#include "Logger.h" #define FIXED_IN_SPACE 1 #define NO_SIM 0 -clock_t ts_start; - static const std::string MODEL_NAME = "LocomotorPrimitives"; +static const double INTEGRATOR_ACCURACY = 1.0e-3; + +static Logger &logger = Logger::getInstance(); static void constructModel(OpenSim::Model &model, OpenSim::Storage actData) { - std::cout << "Constructing " << MODEL_NAME << " model" << std::endl; + logger.log("Constructing model %s\n", MODEL_NAME.c_str()); // Define controller for the model LocomotorPrimitivesController *control = new LocomotorPrimitivesController(actData, 0.01); control->setActuators(model.updActuators()); if (control->checkControls() != 0) { - std::cerr << "Control data for some muscles in the model is missing. ENTER to continue, ^-C to quit." << std::endl; + logger.err("Control data for some muscles in the model is missing. Press ENTER to continue, ^-C to quit."); std::cin.get(); } model.addController(control); @@ -35,12 +37,12 @@ static void constructModel(OpenSim::Model &model, OpenSim::Storage actData) // Set default activation and fiber length on all muscles of the model const OpenSim::Set &actSet = model.getActuators(); int sz = actSet.getSize(); - std::cout << " + Defining initial muscle states for " << sz << " actuators:" << std::endl; + logger.log("+ Defining initial muscle states for %d actuators:\n", sz); // Set default activation and fiber length of all muscles for (int i = 0; i < sz; i++) { OpenSim::ActivationFiberLengthMuscle *m = dynamic_cast(&actSet.get(i)); - std::cout << " " << m->getName() << std::endl; + logger.log(" => %s\n", m->getName().c_str()); // m->setDefaultActivation(0.5); // m->setDefaultFiberLength(0.1); } @@ -50,45 +52,49 @@ static void constructModel(OpenSim::Model &model, OpenSim::Storage actData) OpenSim::ForceReporter *reporter = new OpenSim::ForceReporter(&model); model.addAnalysis(reporter); - std::cout << "Finished constructing model" << std::endl; + logger.log("Finished constructing model\n"); } void simulateModel(OpenSim::Model &model, const double initialTime, const double finalTime) { if (NO_SIM) { - std::cout << "Skipping simulation as per NO_SIM=" << NO_SIM << std::endl; + logger.log("Skipping simulation as per NO_SIM=%d\n", NO_SIM); return; } - std::cout << "Simulating model " << MODEL_NAME << std::endl; - std::cout << " + Initializing system" << std::endl; + logger.log("Simulating model %s\n", MODEL_NAME.c_str()); + + logger.log("+ Initializing system\n"); SimTK::State &si = model.initSystem(); - std::cout << " + Creating integrator" << std::endl; +// std::cout << "=== MODEL SUMMARY ===" << std::endl; +// model.printDetailedInfo(si, std::cout); +// std::cout << "=== END MODEL SUMMARY ===" << std::endl << std::endl; + + logger.log("+ Creating integrator (RungeKuttaMerson) with accuracy %e\n", INTEGRATOR_ACCURACY); // Create the integrator and manager for the simulation SimTK::RungeKuttaMersonIntegrator integrator(model.getMultibodySystem()); - integrator.setAccuracy(1.0e-3); - std::cout << " + Creating simulation manager" << std::endl; + integrator.setAccuracy(INTEGRATOR_ACCURACY); + logger.log("+ Creating simulation manager\n"); LocomotorPrimitivesManager manager(model, integrator); - // Integrate from initial time to final time manager.setInitialTime(initialTime); manager.setFinalTime(finalTime); - - std::cout << "=== MODEL SUMMARY ===" << std::endl; - model.printDetailedInfo(si, std::cout); - std::cout << "=== END MODEL SUMMARY ===" << std::endl << std::endl; - std::cout << " + Integrating from " << std::fixed << initialTime << " to " << std::fixed << finalTime << std::endl; + logger.log("+ Integrating from time %f to %f\n", initialTime, finalTime); manager.integrate(si); // Save the model states from forward integration + logger.log("+ Writing states to %s_states.sto\n", MODEL_NAME.c_str()); OpenSim::Storage statesDegrees(manager.getStateStorage()); statesDegrees.print(MODEL_NAME + "_states.sto"); // Save the forces + logger.log("+ Writing forces to %s_forces.mot\n", MODEL_NAME.c_str()); OpenSim::Analysis &reporter = model.getAnalysisSet()[0]; ((OpenSim::ForceReporter &)reporter).getForceStorage().print(MODEL_NAME + "_forces.mot"); + + logger.log("Finished simulating model\n"); } static void usage() @@ -101,7 +107,7 @@ static void usage() int main(int argc, char **argv) { - ts_start = clock(); + clock_t ts_start = clock(); /* set default values (to work on windows) */ std::string modelFile = FIXED_IN_SPACE ? "../../locomotor-primitives-fixed.osim" : "../../locomotor-primitives.osim"; @@ -130,12 +136,11 @@ int main(int argc, char **argv) const double finalTime = actData.getLastTime(); if (initialTime < 0 || finalTime < 0 || finalTime <= initialTime) { - std::cerr << "invalid time range in data file: " << initialTime << " - " << finalTime << std::endl; + logger.err("invalid time range in data file: %f - %f\n", initialTime, finalTime); exit(-1); } - std::cout << "Starting simulation " + MODEL_NAME << " with (" << modelFile << ", " << dataFile << ") from time " - << initialTime << " to " << finalTime << std::endl; + logger.log("Starting simulation %s with model file %s, actuation data file %s\n", MODEL_NAME.c_str(), modelFile.c_str(), dataFile.c_str()); try { // Create an OpenSim model and set its name @@ -147,22 +152,21 @@ int main(int argc, char **argv) constructModel(osimModel, actData); simulateModel(osimModel, initialTime, finalTime); } catch (OpenSim::Exception ex) { - std::cout << ex.getMessage() << std::endl; + logger.err("Exception: %s. Press ENTER to quit", ex.getMessage()); std::cin.get(); return 1; } catch (std::exception ex) { - std::cout << ex.what() << std::endl; + logger.err("Exception: %s. Press ENTER to quit", ex.what()); std::cin.get(); return 1; } catch (...) { - std::cout << "UNRECOGNIZED EXCEPTION" << std::endl; + logger.err("Unrecognized Exception. Press ENTER to quit"); std::cin.get(); return 1; } - std::cout << "main() routine time = " << 1.e3*(clock()-ts_start)/CLOCKS_PER_SEC << "ms" << std::endl; - - std::cout << "Simulation " + MODEL_NAME << " completed successfully." << std::endl; + logger.log("Total runtime = %fms\n", 1.e3 * (clock() - ts_start) / CLOCKS_PER_SEC); + logger.log("Simulation %s completed successfully. Press ENTER to quit", MODEL_NAME.c_str()); std::cin.get(); return 0; } diff --git a/LocomotorPrimitivesController.cpp b/LocomotorPrimitivesController.cpp index 27ac205..0bdaf81 100644 --- a/LocomotorPrimitivesController.cpp +++ b/LocomotorPrimitivesController.cpp @@ -2,14 +2,11 @@ #include "LocomotorPrimitivesController.h" -#define VERBOSE 1 - -// XXX -extern clock_t ts_start; - static const double TIME_DAMP = 0.1; static const unsigned int N_PRINT = 1000; +static Logger &logger = Logger::getInstance(); + int LocomotorPrimitivesController::checkControls() { const int act_set_siz = getActuatorSet().getSize(); @@ -22,7 +19,7 @@ int LocomotorPrimitivesController::checkControls() const OpenSim::Array indices = _act.getColumnIndicesForIdentifier(muscle->getName()); if (indices.getSize() == 0) { - std::cerr << "Error: no actuation data for muscle '" << muscle->getName() << "' found" << std::endl; + logger.err("no actuation data for muscle '%s' found\n", muscle->getName().c_str()); ret--; } } @@ -52,10 +49,11 @@ void LocomotorPrimitivesController::computeControls(const SimTK::State &s, SimTK if (indices.getSize() != 0) { int idx = indices.get(0) - 1; if (n % N_PRINT == 0) - std::cout << "[" << (1.e3 * clock() - ts_start) / CLOCKS_PER_SEC << "ms] " << t << " (" << idx << ") actuation data for '" << muscle->getName() << "' found: " << _muscle_act[idx] << std::endl; + logger.log("%f (%d) actuation data for muscle '%s' found: %f\n", + t, idx, muscle->getName().c_str(), _muscle_act[idx]); if (_muscle_act[idx] > 1.0) { - std::cerr << "Error: muscle actuation larger than 1.0 (" << _muscle_act[idx] << "), truncating" << std::endl; + logger.err("muscle actuation larger than 1.0 (%f), truncating to 1.0\n", _muscle_act[idx]); _muscle_act[idx] = 1.0; } diff --git a/LocomotorPrimitivesController.h b/LocomotorPrimitivesController.h index c33745e..578a659 100644 --- a/LocomotorPrimitivesController.h +++ b/LocomotorPrimitivesController.h @@ -3,6 +3,8 @@ #include +#include "Logger.h" + class LocomotorPrimitivesController : public OpenSim::Controller { OpenSim_DECLARE_CONCRETE_OBJECT(LocomotorPrimitivesController, OpenSim::Controller); diff --git a/Logger.cpp b/Logger.cpp new file mode 100644 index 0000000..b0850a6 --- /dev/null +++ b/Logger.cpp @@ -0,0 +1,58 @@ +/** + * General purpose logger class. + * + * Copyright (C) 2013 Tobias Klauser + * + * This file is subject to the terms and conditions of the GNU General + * Public License, version 2. + */ + +#include +#include +#include +#include +#include + +#include "Logger.h" + +const char *Logger::_LOGGER_DATE_FMT = "%b %d %Y %H:%M:%S"; + +int Logger::_log_vfprintf(FILE *f, const char *prefix, const char *fmt, va_list ap) +{ + struct timeval now; + char buf[64]; + int ret; + + if (gettimeofday(&now, NULL)) + return -EINVAL; + + strftime(buf, sizeof(buf), _LOGGER_DATE_FMT, localtime(&now.tv_sec)); + ret = fprintf(f, "[%s.%03lu] %s%s", buf, now.tv_usec / 1000, + prefix ? prefix : "", prefix ? ": " : ""); + + return vfprintf(f, fmt, ap); +} + +int Logger::log(const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = _log_vfprintf(_f_out, NULL, fmt, ap); + va_end(ap); + + return ret; +} + +int Logger::err(const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = _log_vfprintf(_f_err, "Error", fmt, ap); + va_end(ap); + + return ret; +} diff --git a/Logger.h b/Logger.h new file mode 100644 index 0000000..5ee5bd4 --- /dev/null +++ b/Logger.h @@ -0,0 +1,42 @@ +/** + * General purpose logger class. + * + * Copyright (C) 2013 Tobias Klauser + * + * This file is subject to the terms and conditions of the GNU General + * Public License, version 2. + */ + +#ifndef LOGGER_H_ +#define LOGGER_H_ + +#include +#include + +/* TODO: Make singleton */ +class Logger { + +public: + static Logger& getInstance() + { + // instantiated on first use, guaranteed to be destroyed + static Logger instance; + return instance; + } + + int log(const char *fmt, ...); + int err(const char *fmt, ...); +private: + Logger() : _f_out(stdout), _f_err(stderr) { } + ~Logger() { } + // Declare copy constructer to prevent the compiler from generating one + Logger(Logger const&); + void operator=(Logger const&); + + FILE *_f_out, *_f_err; + static const char *_LOGGER_DATE_FMT; + + int _log_vfprintf(FILE *f, const char *prefix, const char *fmt, va_list ap); +}; + +#endif /* LOGGER_H_ */ -- cgit v1.2.3-54-g00ecf