#include <InputLogger.h>
Collaboration diagram for gadget::InputLogger:

Public Types | |
| enum | State { Inactive, Recording, Playing, Paused } |
| List of states that the Logger can be in. More... | |
Public Methods | |
| InputLogger () | |
| virtual | ~InputLogger () |
| Destructor. More... | |
| virtual bool | config (jccl::ConfigElementPtr element) |
| Configure the logger. More... | |
| void | process () |
| Do input logging processing. More... | |
Recording interface | |
| void | startRecording () |
| void | stopRecording () |
| void | stampRecord () |
| Collect a stamp in the recording. More... | |
Playback interface | |
| void | load (std::string logFilename) |
| Load a log file. More... | |
| void | play () |
| Play the currently active log. More... | |
| void | stop () |
| Stop playing a log. More... | |
| void | pause () |
| Pause log playback. More... | |
| std::string | getStamp () |
| Get the stamp for the most recent sample. More... | |
Query methods | |
| bool | getState () |
Protected Methods | |
| void | compressSamples () |
| Eliminates duplicates in the current sampled data It ignores the timestamp attribute. More... | |
Internal helpers | |
| void | addRecordingSample () |
| Add a recording sample to the current dom tree. More... | |
| void | playNextSample () |
| void | limitFramerate () |
| Limit the framerate to the speed configured. More... | |
Definition at line 54 of file InputLogger.h.
|
|
List of states that the Logger can be in.
Definition at line 138 of file InputLogger.h.
|
|
|
Definition at line 57 of file InputLogger.h.
00058 : mCurState(Inactive), mSleepFramesLeft(0), mLimitFrameRate(false) 00059 {;} |
|
|
Destructor.
Definition at line 62 of file InputLogger.h.
00063 {;}
|
|
|
Configure the logger.
Definition at line 88 of file InputLogger.cpp. References gadgetDBG_INPUT_MGR, and gadget::BaseDeviceInterface::init.
00089 {
00090 std::string start_name = element->getProperty<std::string>("start_digital");
00091 std::string stamp_name = element->getProperty<std::string>("stamp_digital");
00092
00093 mStartStopButton.init(start_name);
00094 mStampButton.init(stamp_name);
00095
00096 int max_frame_rate = element->getProperty<int>("max_framerate");
00097 mCompressFactor = element->getProperty<unsigned>("compress_factor");
00098
00099 // Get ignore attribs and elems for compressing
00100 unsigned num_ignore_elems, num_ignore_attribs;
00101 num_ignore_elems = element->getNum("ignore_elems");
00102 num_ignore_attribs = element->getNum("ignore_attribs");
00103
00104 for(unsigned i=0;i<num_ignore_elems;i++)
00105 { mIgnoreElems.push_back(element->getProperty<std::string>("ignore_elems",i)); }
00106
00107 for(unsigned i=0;i<num_ignore_attribs;i++)
00108 { mIgnoreAttribs.push_back(element->getProperty<std::string>("ignore_attribs",i)); }
00109
00110 if(max_frame_rate > 0) // If we are supposed to limit frame rate
00111 {
00112 mLimitFrameRate = true;
00113
00114 mPrevFrameTimestamp.setNow(); // Initialize value
00115 mMinFrameTime.set( (1000/max_frame_rate), vpr::Interval::Msec);
00116 }
00117
00118 vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_CONFIG_LVL) << "\n--- LOGGER: Configured ---\n" << vprDEBUG_FLUSH;
00119 vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_CONFIG_LVL) << "StartStop: " << start_name << std::endl
00120 << "Stamp: " << stamp_name << std::endl
00121 << "Max framerate: " << max_frame_rate << std::endl
00122 << "Min frametime: " << mMinFrameTime.msec() << "ms" << std::endl << vprDEBUG_FLUSH;
00123
00124 return true;
00125 }
|
|
|
Do input logging processing. This method is called by the input manager each update frame to allow the logger to do any processing that it needs to complete. Definition at line 142 of file InputLogger.cpp. References addRecordingSample, limitFramerate, Playing, playNextSample, Recording, stampRecord, startRecording, and stopRecording.
00143 {
00144 // Get state of control keys
00145 // Note, because of how this is called this sees the state one frame late
00146 // ie. If toggle on is true here it is NOT true in the data being saved
00147 const bool start_stop_triggered(mStartStopButton->getData() == Digital::TOGGLE_ON);
00148 const bool stamp_triggered(mStampButton->getData() == Digital::TOGGLE_ON);
00149
00150 if(0 == mSleepFramesLeft)
00151 {
00152 // Check for control keys
00153 if(Playing != mCurState)
00154 {
00155 if(start_stop_triggered)
00156 {
00157 if(Recording == mCurState)
00158 { stopRecording(); }
00159 else
00160 { startRecording(); }
00161 }
00162 else if(stamp_triggered && (Recording == mCurState))
00163 { stampRecord(); }
00164 }
00165
00166 if(Recording == mCurState)
00167 {
00168 addRecordingSample();
00169
00170 if(mLimitFrameRate)
00171 { limitFramerate(); }
00172 }
00173 else if(Playing == mCurState)
00174 {
00175 playNextSample();
00176 }
00177 }
00178 else
00179 {
00180 vprDEBUG(vprDBG_ALL, vprDBG_CONFIG_LVL) << "InputLogger: Sleeping: " << mSleepFramesLeft << std::endl << vprDEBUG_FLUSH;
00181 mSleepFramesLeft--;
00182 }
00183 }
|
|
|
Definition at line 191 of file InputLogger.cpp. References gadgetDBG_INPUT_MGR, and Recording. Referenced by process.
00192 {
00193 vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_STATE_LVL) << "\n--- LOGGER: startRecording ---\n" << vprDEBUG_FLUSH;
00194
00195 // -- Get recording filename
00196 std::cout << "/n/n------- LOGGER ------\nEnter log filename:" << std::flush;
00197 std::string file_name;
00198 //std::string file_name("test_logging.xml");
00199 std::cin >> file_name;
00200 std::cout << "\nUsing file: " << file_name << std::endl;
00201
00202 mRecordingFilename = file_name;
00203
00204 // -- Init recording
00205 cppdom::ContextPtr ctx( new cppdom::Context );
00206 mRootNode = cppdom::NodePtr(new cppdom::Node("gadget_logger", ctx ));
00207
00208 mCurState = Recording;
00209 }
|
|
|
Definition at line 211 of file InputLogger.cpp. References compressSamples, gadgetDBG_INPUT_MGR, and Inactive. Referenced by process.
00212 {
00213 vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_STATE_LVL) << "\n--- LOGGER: stopRecording ---\n" << vprDEBUG_FLUSH;
00214 vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_STATE_LVL) << "Done recording\n"
00215 << "Saving data to: " << mRecordingFilename << std::endl << vprDEBUG_FLUSH;
00216
00217 // Compress the data before saving
00218 std::cout << "Before compressing: size:" << mRootNode->getChildren().size() << std::endl;
00219 compressSamples();
00220 std::cout << "After compressing: size:" << mRootNode->getChildren().size() << std::endl;
00221
00222 std::ofstream out_file;
00223 out_file.exceptions(std::ofstream::badbit | std::ofstream::failbit);
00224 try
00225 {
00226 out_file.open(mRecordingFilename.c_str());
00227 mRootNode->save(out_file);
00228 out_file.flush();
00229 out_file.close();
00230 }
00231 #if defined(__GNUC__) && __GNUC__ == 2 && __GNUC_MINOR__ == 96
00232 catch(...)
00233 {
00234 std::cerr << "Unknown error saving file." << std::endl;
00235 if(out_file.is_open())
00236 { out_file.close(); }
00237 }
00238 #else
00239 catch(std::ofstream::failure& se)
00240 {
00241 std::cerr << "IOS failure saving file: desc:" << se.what() << std::endl;
00242 if(out_file.is_open())
00243 { out_file.close(); }
00244 }
00245 catch(...)
00246 {
00247 std::cerr << "Unknown error saving file." << std::endl;
00248 }
00249 #endif
00250
00251 mCurState = Inactive;
00252 mSleepFramesLeft = 10; // Wait 10 frames until we start processing anything again
00253 }
|
|
|
Collect a stamp in the recording.
Definition at line 255 of file InputLogger.cpp. References Recording. Referenced by process.
00256 {
00257 vprASSERT(Recording == mCurState && "Tried to stamp input while not recording");
00258
00259 // -- Get recording filename
00260 char tag_name[1024];
00261 std::cout << "/n/n------- LOGGER ------\nEnter stamp id:" << std::flush;
00262 std::string stamp_id;
00263 //std::cin >> stamp_id;
00264 scanf("%s", tag_name);
00265 stamp_id = std::string(tag_name);
00266 std::cout << "\nStamping with: " << stamp_id << std::endl;
00267
00268 cppdom::NodePtr stamp_node(new cppdom::Node("stamp", mRootNode->getContext()));
00269 stamp_node->setAttribute("id", stamp_id);
00270
00271 mRootNode->addChild(stamp_node);
00272 }
|
|
|
Load a log file.
Definition at line 277 of file InputLogger.cpp. References Inactive.
00278 {
00279 vprASSERT(Inactive == mCurState && "Tried to load a file while logger is active");
00280
00281 std::cout << "InputLogger: Loading file: " << logFilename << std::endl;
00282
00283 // Create new root to read into
00284 cppdom::ContextPtr ctx( new cppdom::Context );
00285 mRootNode = cppdom::NodePtr(new cppdom::Node("not_set", ctx ));
00286
00287 std::ifstream in_file;
00288 in_file.exceptions(std::ifstream::badbit | std::ifstream::failbit);
00289 try
00290 {
00291 in_file.open(logFilename.c_str(), std::ios::in);
00292 mRootNode->load(in_file, ctx);
00293 in_file.close();
00294 }
00295 #if defined(__GNUC__) && __GNUC__ == 2 && __GNUC_MINOR__ == 96
00296 catch(...)
00297 {
00298 std::cerr << "Unknown error loading file." << std::endl;
00299 if(in_file.is_open())
00300 { in_file.close(); }
00301 }
00302 #else
00303 catch(std::ifstream::failure& se)
00304 {
00305 std::cerr << "IOS failure saving file: desc:" << se.what() << std::endl;
00306 if(in_file.is_open())
00307 { in_file.close(); }
00308 }
00309 catch(...)
00310 {
00311 std::cerr << "Unknown error loading file." << std::endl;
00312 }
00313 #endif
00314
00315 vprDEBUG(vprDBG_ALL, vprDBG_STATE_LVL) << "InputLogger: Loaded file: num_samples:" << mRootNode->getChildren().size() << std::endl << vprDEBUG_FLUSH;
00316 }
|
|
|
Play the currently active log.
Definition at line 325 of file InputLogger.cpp. References Inactive, and Playing.
00326 {
00327 vprASSERT(mCurState == Inactive);
00328
00329 if(mRootNode.get() == NULL)
00330 {
00331 vprDEBUG(vprDBG_ALL, vprDBG_WARNING_LVL) << "Logger::play: Null root node, so can't play.\n" << vprDEBUG_FLUSH;
00332 return;
00333 }
00334
00335 mNextSample_i = mRootNode->getChildren().begin();
00336 mEndSample_i = mRootNode->getChildren().end();
00337 mActiveStamp.clear();
00338
00339 if(mNextSample_i == mEndSample_i)
00340 {
00341 vprDEBUG(vprDBG_ALL, vprDBG_WARNING_LVL) << "Logger::play: Zero children, so can't play.\n" << vprDEBUG_FLUSH;
00342 return;
00343 }
00344
00345 mCurState = Playing;
00346 }
|
|
|
Stop playing a log.
Definition at line 349 of file InputLogger.cpp.
00350 {;
00351 }
|
|
|
Pause log playback.
Definition at line 354 of file InputLogger.cpp.
00355 {;
00356 }
|
|
|
Get the stamp for the most recent sample.
Definition at line 361 of file InputLogger.cpp.
00362 {
00363 return mActiveStamp;
00364 }
|
|
|
Definition at line 112 of file InputLogger.h.
00113 { return mCurState; }
|
|
|
Add a recording sample to the current dom tree.
Definition at line 377 of file InputLogger.cpp. References gadgetDBG_INPUT_MGR, gadget::Input::getInstanceName, and gadget::Input::writeObject. Referenced by process.
00378 {
00379 vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_STATE_LVL) << "LOGGER: adding sample.\n" << vprDEBUG_FLUSH;
00380
00381 try
00382 {
00383 gadget::InputManager* input_mgr = gadget::InputManager::instance();
00384
00385 cppdom::NodePtr sample_node(new cppdom::Node("sample", mRootNode->getContext()));
00386
00387 // For each device
00388 for(InputManager::tDevTableType::iterator dev_i=input_mgr->mDevTable.begin();
00389 dev_i != input_mgr->mDevTable.end(); ++dev_i)
00390 {
00391 gadget::Input* cur_dev = (*dev_i).second;
00392 std::string dev_name = cur_dev->getInstanceName();
00393
00394 cppdom::NodePtr dev_node(new cppdom::Node("device", mRootNode->getContext()));
00395 dev_node->setAttribute("dev_name", dev_name);
00396
00397 vpr::XMLObjectWriter xml_writer; // Create writer for the device
00398 cur_dev->writeObject(&xml_writer);
00399 cppdom::NodePtr serialized_dev_node = xml_writer.getRootNode();
00400 vprASSERT(serialized_dev_node.get() != NULL);
00401
00402 dev_node->addChild(serialized_dev_node); // Add the child node
00403 sample_node->addChild(dev_node); // Add dev node to the sample
00404 }
00405
00406 mRootNode->addChild(sample_node);
00407 }
00408 catch (cppdom::Error& ce)
00409 {
00410 std::cerr << "Cppdom Error [InputLogger::addRecordingSample]: " << ce.getString() << std::endl;
00411 std::cerr << "Info: " << ce.getInfo() << std::endl;
00412 vprASSERT(false);
00413 }
00414 }
|
|
|
Definition at line 429 of file InputLogger.cpp. References gadgetDBG_INPUT_MGR, Inactive, and gadget::Input::readObject. Referenced by process.
00430 {
00431 vprDEBUG_OutputGuard(gadgetDBG_INPUT_MGR, vprDBG_STATE_LVL, "InputLogger::playNextSample\n", "done playing sample\n");
00432
00433 vprASSERT(mNextSample_i != mEndSample_i && "Overran the logger sample list");
00434 gadget::InputManager* input_mgr = gadget::InputManager::instance();
00435
00436 cppdom::NodePtr next_node = (*mNextSample_i);
00437 vprASSERT(next_node->getName() == std::string("sample") && "Didn't get element of name sample");
00438
00439 // For each device element
00440 cppdom::NodeList dev_nodes = next_node->getChildren();
00441 for(cppdom::NodeListIterator cur_dev_node=dev_nodes.begin(); cur_dev_node != dev_nodes.end(); ++cur_dev_node)
00442 {
00443 vprASSERT((*cur_dev_node)->getName() == std::string("device"));
00444 std::string dev_name = (*cur_dev_node)->getAttribute("dev_name").getValue<std::string>();
00445 cppdom::NodePtr serial_dev_node = *((*cur_dev_node)->getChildren().begin());
00446 vprASSERT(serial_dev_node.get() != NULL && "Got null serialized device node");
00447
00448 gadget::Input* dev_ptr = input_mgr->getDevice(dev_name);
00449 if(NULL != dev_ptr)
00450 {
00451 vprDEBUG_OutputGuard(gadgetDBG_INPUT_MGR, vprDBG_STATE_LVL,
00452 std::string("Reading device: ") + dev_name + std::string("\n"), "done reading");
00453
00454 vpr::XMLObjectReader xml_reader(serial_dev_node); // Create XML reader
00455 xml_reader.setAttrib("rim.timestamp.delta", 0); // Hack for now to work around RIM
00456 dev_ptr->readObject(&xml_reader); // Deserialize the device
00457 }
00458 else
00459 {
00460 vprDEBUG(gadgetDBG_INPUT_MGR,vprDBG_WARNING_LVL) << "Skipping device: [" << dev_name
00461 << "] Could not find it.\n" << vprDEBUG_FLUSH;
00462 }
00463 }
00464
00465 // Increment next sample
00466 mNextSample_i++;
00467 mActiveStamp.clear(); // Clear the stamp for now
00468
00469 if(mNextSample_i != mEndSample_i)
00470 {
00471 if( (*mNextSample_i)->getName() == std::string("stamp"))
00472 {
00473 mActiveStamp = (*mNextSample_i)->getAttribute("id").getValue<std::string>();
00474 mNextSample_i++;
00475 vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_STATE_LVL) << "Logger: Got stamp: [" << mActiveStamp << "]\n" << vprDEBUG_FLUSH;
00476 }
00477 }
00478
00479 if(mNextSample_i == mEndSample_i) // If done playing
00480 {
00481 mCurState = Inactive;
00482 mSleepFramesLeft = 10; // Wait 10 frames until we start processing anything again
00483 vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_STATE_LVL) << "Logger: Done playing.\n" << vprDEBUG_FLUSH;
00484 }
00485
00486 }
|
|
|
Limit the framerate to the speed configured.
Definition at line 488 of file InputLogger.cpp. Referenced by process.
00489 {
00490 vprASSERT(mLimitFrameRate);
00491
00492 vpr::Interval cur_frame_time = vpr::Interval::now() - mPrevFrameTimestamp;
00493 if(cur_frame_time < mMinFrameTime)
00494 {
00495 vpr::Interval sleep_time = (mMinFrameTime - cur_frame_time);
00496 std::cout << "Sleeping: " << sleep_time.msec() << "ms\n";
00497 vprASSERT(sleep_time.msec() > 0);
00498 vpr::System::msleep(sleep_time.msec()); // Sleep
00499 }
00500
00501 mPrevFrameTimestamp.setNow();
00502 }
|
|
|
Eliminates duplicates in the current sampled data It ignores the timestamp attribute.
Definition at line 504 of file InputLogger.cpp. Referenced by stopRecording.
00505 {
00506 // Get the current children to compress
00507 cppdom::NodeList& nodes(mRootNode->getChildren());
00508 unsigned total_nodes_start = nodes.size();
00509
00510 // Create a nice little progress bar for the compression
00511 boost::progress_display compress_progress(nodes.size());
00512
00513 cppdom::NodeList::iterator cur_node = nodes.begin();
00514 if(nodes.end() == cur_node)
00515 return;
00516
00517 cur_node++; // Can't remove first node
00518 //unsigned node_index(0);
00519
00520 // Compress the data
00521 // - While nodes left
00522 // - If node is duplicate of one before it
00523 // - Erase the node and goto next
00524 while(cur_node != nodes.end())
00525 {
00526 cppdom::NodeList::iterator dup_node = (cur_node-1); // Initialize dup node to check
00527
00528 /*
00529 std::cout << "-----------------------------------------------------------------------\n"
00530 << "-----------------------------------------------------------------------\n"
00531 << "Comparing nodes: index: " << node_index++ << std::endl;
00532 std::cout << "------ curnode:\n";
00533 (*cur_node)->save(std::cout, 1);
00534 std::cout << "------ dupnode:\n";
00535 (*dup_node)->save(std::cout, 1);
00536 std::cout << "------ Start comparison ----\n";
00537 */
00538
00539 if((*cur_node)->isEqual( *dup_node, mIgnoreAttribs, mIgnoreElems))
00540 {
00541 cur_node = nodes.erase(cur_node); // Remove the node and get next one
00542 }
00543 else
00544 {
00545 cur_node++; // Go to the next
00546 }
00547
00548 compress_progress += 1; // Progress a little bit
00549 }
00550
00551 // --- Print results --- //
00552 std::cout << std::endl
00553 << "Compression: initial/compressed:" << total_nodes_start << "/" << nodes.size() << std::endl
00554 << " ratio: " << float(nodes.size())/float(total_nodes_start) << std::endl;
00555 }
|
1.2.14 written by Dimitri van Heesch,
© 1997-2002