Skip to content

Commit

Permalink
Working data manager infrastructure! tgDataLogger2 is now handled pro…
Browse files Browse the repository at this point in the history
…perly by tgSimulation. Next step is creating and destroying the sensors themselves.
  • Loading branch information
apsabelhaus committed Jan 6, 2017
1 parent 3d599b3 commit db7e5ce
Show file tree
Hide file tree
Showing 7 changed files with 242 additions and 6 deletions.
Expand Up @@ -33,6 +33,7 @@
#include "core/tgSimViewGraphics.h" #include "core/tgSimViewGraphics.h"
#include "core/tgSimulation.h" #include "core/tgSimulation.h"
#include "core/tgWorld.h" #include "core/tgWorld.h"
#include "sensors/tgDataLogger2.h"
// Bullet Physics // Bullet Physics
#include "LinearMath/btVector3.h" #include "LinearMath/btVector3.h"
// The C++ Standard Library // The C++ Standard Library
Expand Down Expand Up @@ -79,6 +80,15 @@ int main(int argc, char** argv)


// Finally, add out model to the simulation // Finally, add out model to the simulation
simulation.addModel(myModel); simulation.addModel(myModel);

// For the sensors:
// A string prefix for the filename
std::string log_filename = "~/NTRTsim_logs/AppTgBoxAnchorDebugDemo";
// First, create the data manager
tgDataLogger2* myDataLogger = new tgDataLogger2(log_filename);
// Next, attach it to the simulation
simulation.addDataManager(myDataLogger);
// and everything else should happen automatically.


// Run until the user stops // Run until the user stops
simulation.run(); simulation.run();
Expand Down
1 change: 1 addition & 0 deletions src/sensors/CMakeLists.txt
Expand Up @@ -10,6 +10,7 @@ add_library( ${PROJECT_NAME} SHARED


# For the new sensors # For the new sensors
tgDataManager.cpp tgDataManager.cpp
tgDataLogger2.cpp
tgSensor.cpp tgSensor.cpp
tgRodSensor.cpp tgRodSensor.cpp
) )
Binary file modified src/sensors/SensorsRedesignOutline_2017-01-03.docx
Binary file not shown.
153 changes: 153 additions & 0 deletions src/sensors/tgDataLogger2.cpp
@@ -0,0 +1,153 @@
/*
* Copyright © 2012, United States Government, as represented by the
* Administrator of the National Aeronautics and Space Administration.
* All rights reserved.
*
* The NASA Tensegrity Robotics Toolkit (NTRT) v1 platform is licensed
* under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

/**
* @file tgDataLogger2.cpp
* @brief Contains the implementation of concrete class tgDataLogger2
* @author Drew Sabelhaus
* $Id$
*/

// This module
//#include "tgDataManager.h"
#include "tgDataLogger2.h"
// This application
#include "tgSensor.h"
//#include "tgSensorInfo.h"
// The C++ Standard Library
//#include <stdio.h> // for sprintf
#include <stdexcept>
#include <cassert>
#include <iostream>

/**
* The constructor for this class only assigns the filename prefix.
* The actual filename is created in setup.
* This makes it so that, upon reset, a new log file is opened (instead of
* appending to the same one.)
* Call the constructor of the parent class anyway, though it does nothing.
*/
tgDataLogger2::tgDataLogger2(std::string fileNamePrefix) :
tgDataManager(),
m_fileNamePrefix(fileNamePrefix)
{
//DEBUGGING
std::cout << "tgDataLogger2 constructor." << std::endl;
// Postcondition
assert(invariant());
}

/**
* The destructor should not have to do anything.
* Closing the log file is handled by teardown(), and the parent class
* handles deletion of the sensors and sensor infos.
*/
tgDataLogger2::~tgDataLogger2()
{
//DEBUGGING
std::cout << "tgDataLogger2 destructor." << std::endl;
}

/**
* Setup will do three things:
* (1) create the full filename, based on the current time from the operating system,
* (2) create the sensors based on the sensor infos that have been added and
* the senseable objects that have also been added,
* (3) opens the log file and writes a heading line (then closes the file.)
*/
void tgDataLogger2::setup()
{
// Although the parent class doesn't do much in setup at the moment,
// call it here anyway, in case that changes!
tgDataManager::setup();
//DEBUGGING
std::cout << "tgDataLogger2 setup." << std::endl;
// TO-DO: setup everything!

// Postcondition
assert(invariant());
}

/**
* The parent's teardown method handles the sensors and sensor infos.
*/
void tgDataLogger2::teardown()
{
// Call the parent's teardown method! This is important!
tgDataManager::teardown();
//DEBUGGING
std::cout << "tgDataLogger2 teardown." << std::endl;
// Postcondition
assert(invariant());
}

/**
* The step method is where data is actually collected!
* This data logger will do two things here:
* (1) iterate through all the sensors, collect their data,
* (2) write that line of data to the log file (then close the log again.)
*/
void tgDataLogger2::step(double dt)
{
//DEBUGGING
//std::cout << "tgDataLogger2 step." << std::endl;
if (dt <= 0.0)
{
throw std::invalid_argument("dt is not positive");
}
else
{
//DEBUGGING
//std::cout << "tgDataLogger2 step." << std::endl;
// TO-DO: collect the data.
}

// Postcondition
assert(invariant());
}

/**
* The toString method for tgDataLogger2 should have some specific information
* about (for example) the log file...
*/
std::string tgDataLogger2::toString() const
{
std::string p = " ";
std::ostringstream os;
// Note that we're using sprintf here to convert an int to a string.
// TO-DO: fix this!
os << "tgDataLogger2" << std::endl;
// << " with " << sprintf("%d",m_sensors.size()) << " sensors."<< std::endl;

/*
os << prefix << p << "Children:" << std::endl;
for(std::size_t i = 0; i < m_children.size(); i++) {
os << m_children[i]->toString(prefix + p) << std::endl;
}
os << prefix << p << "Tags: [" << getTags() << "]" << std::endl;
os << prefix << ")";
*/
return os.str();
}

std::ostream&
operator<<(std::ostream& os, const tgDataLogger2& obj)
{
os << obj.toString() << std::endl;
return os;
}
22 changes: 20 additions & 2 deletions src/sensors/tgDataLogger2.h
Expand Up @@ -82,10 +82,28 @@ class tgDataLogger2 : public tgDataManager
protected: protected:


/** /**
* Store the full name of the file for writing data, as well as * Store the full name of the file for writing data.
* note that this is NOT what is passed into the constructor:
* that string is modified to create m_fileName.
*/ */
std::string m_fileName;

/**
* In order to have the filename for the log file be created in
* the setup function, instead of in the constructor, we need to hold
* the filename prefix too. This allows for running setup and teardown
* and having different log files - e.g., when the space bar is pressed,
* a new log file will be opened.
*/
std::string m_fileNamePrefix;

/**
* Keep track of the total time that the simulation has run.
* This is for adding a timestamp into the log file.
*/
double m_totalTime;


} };




#endif // TG_DATA_LOGGER2_H #endif // TG_DATA_LOGGER2_H
46 changes: 43 additions & 3 deletions src/sensors/tgDataManager.cpp
Expand Up @@ -27,9 +27,11 @@
#include "tgDataManager.h" #include "tgDataManager.h"
// This application // This application
#include "tgSensor.h" #include "tgSensor.h"
#include "core/tgSenseable.h"
//#include "tgSensorInfo.h" //#include "tgSensorInfo.h"
// The C++ Standard Library // The C++ Standard Library
//#include <stdio.h> // for sprintf //#include <stdio.h> // for sprintf
#include <iostream>
#include <stdexcept> #include <stdexcept>
#include <cassert> #include <cassert>


Expand All @@ -38,6 +40,8 @@
*/ */
tgDataManager::tgDataManager() tgDataManager::tgDataManager()
{ {
//DEBUGGING
std::cout << "tgDataManager constructor." << std::endl;
// Postcondition // Postcondition
assert(invariant()); assert(invariant());
} }
Expand All @@ -50,6 +54,9 @@ tgDataManager::tgDataManager()
*/ */
tgDataManager::~tgDataManager() tgDataManager::~tgDataManager()
{ {
//DEBUGGING
std::cout << "tgDataManager destructor." << std::endl;

// First, delete everything in m_sensors. // First, delete everything in m_sensors.
const size_t n_Sens = m_sensors.size(); const size_t n_Sens = m_sensors.size();
for (size_t i = 0; i < n_Sens; ++i) for (size_t i = 0; i < n_Sens; ++i)
Expand All @@ -63,6 +70,10 @@ tgDataManager::~tgDataManager()
} }
// Next, delete the sensor infos. // Next, delete the sensor infos.
// TO-DO: fill in. // TO-DO: fill in.

// Note that the creation and deletion of the senseable objects, e.g.
// the tgModels, is handled externally.
// tgDataManagers should NOT destroy the objects they are sensing.
} }


/** /**
Expand All @@ -71,6 +82,8 @@ tgDataManager::~tgDataManager()
*/ */
void tgDataManager::setup() void tgDataManager::setup()
{ {
//DEBUGGING
std::cout << "tgDataManager setup." << std::endl;
// TO-DO: Should we create the sensors here in the setup method of the base? // TO-DO: Should we create the sensors here in the setup method of the base?
// What's the best way to maximize code re-use? // What's the best way to maximize code re-use?
// Postcondition // Postcondition
Expand All @@ -79,13 +92,16 @@ void tgDataManager::setup()


/** /**
* The teardown method has to remove all the sensors and sensor infos. * The teardown method has to remove all the sensors and sensor infos.
* Note that this method will likely be re-defined by subclasses, * Note that this method could be redefined by subclasses, for example to
* in order to manage (for example) log files: close them out, for example. * do some final step with a mesage-passing algorithm before the simulation ends.
* TO-DO: what's a good way to capture the deletion of sensors and sensorInfos * TO-DO: what's a good way to capture the deletion of sensors and sensorInfos
* that doesn't require subclasses to copy-and-paste from this teardown method? * that doesn't require subclasses to copy-and-paste from this teardown method?
*/ */
void tgDataManager::teardown() void tgDataManager::teardown()
{ {
//DEBUGGING
std::cout << "tgDataManager teardown." << std::endl;

// First, delete the sensors. // First, delete the sensors.
// Note that it's good practice to set deleted pointers to NULL here. // Note that it's good practice to set deleted pointers to NULL here.
for (std::size_t i = 0; i < m_sensors.size(); i++) for (std::size_t i = 0; i < m_sensors.size(); i++)
Expand All @@ -112,6 +128,8 @@ void tgDataManager::teardown()
*/ */
void tgDataManager::step(double dt) void tgDataManager::step(double dt)
{ {
//DEBUGGING
std::cout << "tgDataManager step." << std::endl;
if (dt <= 0.0) if (dt <= 0.0)
{ {
throw std::invalid_argument("dt is not positive"); throw std::invalid_argument("dt is not positive");
Expand Down Expand Up @@ -139,14 +157,36 @@ void tgDataManager::addSensorInfo(tgSensorInfo* pSensorInfo)
throw std::invalid_argument("pSensorInfo is NULL inside tgDataManager::addSensorInfo"); throw std::invalid_argument("pSensorInfo is NULL inside tgDataManager::addSensorInfo");
} }
m_sensorInfos.push_back(pChild); m_sensorInfos.push_back(pSensorInfo);
// Postcondition // Postcondition
assert(invariant()); assert(invariant());
assert(!m_sensorInfos.empty()); assert(!m_sensorInfos.empty());
} }
*/ */


/**
* This method adds sense-able objects to this data manager.
* It takes in a pointer to a sense-able object and pushes it to the
* current list of tgSenseables.
*/
/*
void tgDataManager::addSenseable(tgSensable* pSenseable)
{
// Precondition
if (pSenseable == NULL)
{
throw std::invalid_argument("pSenseable is NULL inside tgDataManager::addSensable");
}
m_senseables.push_back(pSenseable);
// Postcondition
assert(invariant());
assert(!m_senseables.empty());
}
*/

/** /**
* The toString method for data managers should include a list of the number * The toString method for data managers should include a list of the number
* of sensors and sensor Infos it has. * of sensors and sensor Infos it has.
Expand Down
16 changes: 15 additions & 1 deletion src/sensors/tgDataManager.h
Expand Up @@ -30,7 +30,7 @@
//#include "tgCast.h" //#include "tgCast.h"
//#include "tgTaggable.h" //#include "tgTaggable.h"
//#include "tgTagSearch.h" //#include "tgTagSearch.h"
//#include "tgSenseable.h" //#include "core/tgSenseable.h"
// The C++ Standard Library // The C++ Standard Library
#include <string> #include <string>
#include <sstream> #include <sstream>
Expand All @@ -40,6 +40,7 @@
// Forward declarations // Forward declarations
//class tgWorld; //class tgWorld;
class tgSensor; class tgSensor;
class tgSenseable;
//class tgSensorInfo; //class tgSensorInfo;


/** /**
Expand Down Expand Up @@ -84,6 +85,13 @@ class tgDataManager
*/ */
virtual void step(double dt); virtual void step(double dt);


/**
* Add a tgSenseable object to this data manager.
* These objects will be checked via the sensor infos, and sensors will
* be assigned to them if appropriate.
*/
//virtual void addSenseable(tgSenseable* pSenseable);

/** /**
* Add a sensor info object to the current list of sensor infos. * Add a sensor info object to the current list of sensor infos.
* @param[in] pSensorInfo a pointer to a tgSensorInfo. * @param[in] pSensorInfo a pointer to a tgSensorInfo.
Expand Down Expand Up @@ -116,6 +124,12 @@ class tgDataManager
*/ */
//std::vector<tgSensorInfo*> m_sensorInfos; //std::vector<tgSensorInfo*> m_sensorInfos;


/**
* A data manager will also have a list of tgSenseable objects
* (really, just tgModels most of the time) that it will collect data from.
*/
//std::vector<tgSenseable*> m_senseables;

}; };


/** /**
Expand Down

0 comments on commit db7e5ce

Please sign in to comment.