00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <gadget/gadgetConfig.h>
00034
00035 #include <fstream>
00036 #include <stdio.h>
00037 #include <boost/progress.hpp>
00038 #include <cppdom/cppdom.h>
00039
00040 #include <vpr/vpr.h>
00041 #include <vpr/IO/XMLObjectWriter.h>
00042 #include <vpr/IO/XMLObjectReader.h>
00043 #include <vpr/System.h>
00044 #include <jccl/Config/ConfigElement.h>
00045
00046 #include <gadget/InputLogger.h>
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 namespace gadget
00085 {
00086
00088 bool InputLogger::config( jccl::ConfigElementPtr element)
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
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)
00111 {
00112 mLimitFrameRate = true;
00113
00114 mPrevFrameTimestamp.setNow();
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 }
00126
00142 void InputLogger::process()
00143 {
00144
00145
00146
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
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 }
00184
00185
00186
00187
00188
00189
00190
00191 void InputLogger::startRecording()
00192 {
00193 vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_STATE_LVL) << "\n--- LOGGER: startRecording ---\n" << vprDEBUG_FLUSH;
00194
00195
00196 std::cout << "/n/n------- LOGGER ------\nEnter log filename:" << std::flush;
00197 std::string file_name;
00198
00199 std::cin >> file_name;
00200 std::cout << "\nUsing file: " << file_name << std::endl;
00201
00202 mRecordingFilename = file_name;
00203
00204
00205 cppdom::ContextPtr ctx( new cppdom::Context );
00206 mRootNode = cppdom::NodePtr(new cppdom::Node("gadget_logger", ctx ));
00207
00208 mCurState = Recording;
00209 }
00210
00211 void InputLogger::stopRecording()
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
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;
00253 }
00254
00255 void InputLogger::stampRecord()
00256 {
00257 vprASSERT(Recording == mCurState && "Tried to stamp input while not recording");
00258
00259
00260 char tag_name[1024];
00261 std::cout << "/n/n------- LOGGER ------\nEnter stamp id:" << std::flush;
00262 std::string stamp_id;
00263
00264 #if defined(_MSC_VER) && _MSC_VER >= 1400
00265 scanf_s("%s", tag_name);
00266 #else
00267 scanf("%s", tag_name);
00268 #endif
00269 stamp_id = std::string(tag_name);
00270 std::cout << "\nStamping with: " << stamp_id << std::endl;
00271
00272 cppdom::NodePtr stamp_node(new cppdom::Node("stamp", mRootNode->getContext()));
00273 stamp_node->setAttribute("id", stamp_id);
00274
00275 mRootNode->addChild(stamp_node);
00276 }
00277
00282 void InputLogger::load(std::string logFilename)
00283 {
00284 vprASSERT(Inactive == mCurState && "Tried to load a file while logger is active");
00285
00286 std::cout << "InputLogger: Loading file: " << logFilename << std::endl;
00287
00288
00289 cppdom::ContextPtr ctx( new cppdom::Context );
00290 mRootNode = cppdom::NodePtr(new cppdom::Node("not_set", ctx ));
00291
00292 std::ifstream in_file;
00293 in_file.exceptions(std::ifstream::badbit | std::ifstream::failbit);
00294 try
00295 {
00296 in_file.open(logFilename.c_str(), std::ios::in);
00297 mRootNode->load(in_file, ctx);
00298 in_file.close();
00299 }
00300 #if defined(__GNUC__) && __GNUC__ == 2 && __GNUC_MINOR__ == 96
00301 catch(...)
00302 {
00303 std::cerr << "Unknown error loading file." << std::endl;
00304 if(in_file.is_open())
00305 { in_file.close(); }
00306 }
00307 #else
00308 catch(std::ifstream::failure& se)
00309 {
00310 std::cerr << "IOS failure saving file: desc:" << se.what() << std::endl;
00311 if(in_file.is_open())
00312 { in_file.close(); }
00313 }
00314 catch(...)
00315 {
00316 std::cerr << "Unknown error loading file." << std::endl;
00317 }
00318 #endif
00319
00320 vprDEBUG(vprDBG_ALL, vprDBG_STATE_LVL) << "InputLogger: Loaded file: num_samples:" << mRootNode->getChildren().size() << std::endl << vprDEBUG_FLUSH;
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330 void InputLogger::play()
00331 {
00332 vprASSERT(mCurState == Inactive);
00333
00334 if(mRootNode.get() == NULL)
00335 {
00336 vprDEBUG(vprDBG_ALL, vprDBG_WARNING_LVL) << "Logger::play: Null root node, so can't play.\n" << vprDEBUG_FLUSH;
00337 return;
00338 }
00339
00340 mNextSample_i = mRootNode->getChildren().begin();
00341 mEndSample_i = mRootNode->getChildren().end();
00342 mActiveStamp.clear();
00343
00344 if(mNextSample_i == mEndSample_i)
00345 {
00346 vprDEBUG(vprDBG_ALL, vprDBG_WARNING_LVL) << "Logger::play: Zero children, so can't play.\n" << vprDEBUG_FLUSH;
00347 return;
00348 }
00349
00350 mCurState = Playing;
00351 }
00352
00354 void InputLogger::stop()
00355 {;
00356 }
00357
00359 void InputLogger::pause()
00360 {;
00361 }
00362
00366 std::string InputLogger::getStamp()
00367 {
00368 return mActiveStamp;
00369 }
00370
00371
00382 void InputLogger::addRecordingSample()
00383 {
00384 vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_STATE_LVL) << "LOGGER: adding sample.\n" << vprDEBUG_FLUSH;
00385
00386 try
00387 {
00388 gadget::InputManager* input_mgr = gadget::InputManager::instance();
00389
00390 cppdom::NodePtr sample_node(new cppdom::Node("sample", mRootNode->getContext()));
00391
00392
00393 for(InputManager::tDevTableType::iterator dev_i=input_mgr->mDevTable.begin();
00394 dev_i != input_mgr->mDevTable.end(); ++dev_i)
00395 {
00396 gadget::Input* cur_dev = (*dev_i).second;
00397 std::string dev_name = cur_dev->getInstanceName();
00398
00399 cppdom::NodePtr dev_node(new cppdom::Node("device", mRootNode->getContext()));
00400 dev_node->setAttribute("dev_name", dev_name);
00401
00402 vpr::XMLObjectWriter xml_writer;
00403 cur_dev->writeObject(&xml_writer);
00404 cppdom::NodePtr serialized_dev_node = xml_writer.getRootNode();
00405 vprASSERT(serialized_dev_node.get() != NULL);
00406
00407 dev_node->addChild(serialized_dev_node);
00408 sample_node->addChild(dev_node);
00409 }
00410
00411 mRootNode->addChild(sample_node);
00412 }
00413 catch (cppdom::Error& ce)
00414 {
00415 std::cerr << "Cppdom Error [InputLogger::addRecordingSample]: " << ce.getString() << std::endl;
00416 std::cerr << "Info: " << ce.getInfo() << std::endl;
00417 vprASSERT(false);
00418 }
00419 }
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434 void InputLogger::playNextSample()
00435 {
00436 vprDEBUG_OutputGuard(gadgetDBG_INPUT_MGR, vprDBG_STATE_LVL, "InputLogger::playNextSample\n", "done playing sample\n");
00437
00438 vprASSERT(mNextSample_i != mEndSample_i && "Overran the logger sample list");
00439 gadget::InputManager* input_mgr = gadget::InputManager::instance();
00440
00441 cppdom::NodePtr next_node = (*mNextSample_i);
00442 vprASSERT(next_node->getName() == std::string("sample") && "Didn't get element of name sample");
00443
00444
00445 cppdom::NodeList dev_nodes = next_node->getChildren();
00446 for(cppdom::NodeListIterator cur_dev_node=dev_nodes.begin(); cur_dev_node != dev_nodes.end(); ++cur_dev_node)
00447 {
00448 vprASSERT((*cur_dev_node)->getName() == std::string("device"));
00449 std::string dev_name = (*cur_dev_node)->getAttribute("dev_name").getValue<std::string>();
00450 cppdom::NodePtr serial_dev_node = *((*cur_dev_node)->getChildren().begin());
00451 vprASSERT(serial_dev_node.get() != NULL && "Got null serialized device node");
00452
00453 gadget::Input* dev_ptr = input_mgr->getDevice(dev_name);
00454 if(NULL != dev_ptr)
00455 {
00456 vprDEBUG_OutputGuard(gadgetDBG_INPUT_MGR, vprDBG_STATE_LVL,
00457 std::string("Reading device: ") + dev_name + std::string("\n"), "done reading");
00458
00459 vpr::XMLObjectReader xml_reader(serial_dev_node);
00460 xml_reader.setAttrib("rim.timestamp.delta", 0);
00461 dev_ptr->readObject(&xml_reader);
00462 }
00463 else
00464 {
00465 vprDEBUG(gadgetDBG_INPUT_MGR,vprDBG_WARNING_LVL) << "Skipping device: [" << dev_name
00466 << "] Could not find it.\n" << vprDEBUG_FLUSH;
00467 }
00468 }
00469
00470
00471 mNextSample_i++;
00472 mActiveStamp.clear();
00473
00474 if(mNextSample_i != mEndSample_i)
00475 {
00476 if( (*mNextSample_i)->getName() == std::string("stamp"))
00477 {
00478 mActiveStamp = (*mNextSample_i)->getAttribute("id").getValue<std::string>();
00479 mNextSample_i++;
00480 vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_STATE_LVL) << "Logger: Got stamp: [" << mActiveStamp << "]\n" << vprDEBUG_FLUSH;
00481 }
00482 }
00483
00484 if(mNextSample_i == mEndSample_i)
00485 {
00486 mCurState = Inactive;
00487 mSleepFramesLeft = 10;
00488 vprDEBUG(gadgetDBG_INPUT_MGR, vprDBG_STATE_LVL) << "Logger: Done playing.\n" << vprDEBUG_FLUSH;
00489 }
00490
00491 }
00492
00493 void InputLogger::limitFramerate()
00494 {
00495 vprASSERT(mLimitFrameRate);
00496
00497 vpr::Interval cur_frame_time = vpr::Interval::now() - mPrevFrameTimestamp;
00498 if(cur_frame_time < mMinFrameTime)
00499 {
00500 vpr::Interval sleep_time = (mMinFrameTime - cur_frame_time);
00501 std::cout << "Sleeping: " << sleep_time.msec() << "ms\n";
00502 vprASSERT(sleep_time.msec() > 0);
00503 vpr::System::msleep(sleep_time.msec());
00504 }
00505
00506 mPrevFrameTimestamp.setNow();
00507 }
00508
00509 void InputLogger::compressSamples()
00510 {
00511
00512 cppdom::NodeList& nodes(mRootNode->getChildren());
00513 unsigned total_nodes_start = nodes.size();
00514
00515
00516 boost::progress_display compress_progress(nodes.size());
00517
00518 cppdom::NodeList::iterator cur_node = nodes.begin();
00519 if(nodes.end() == cur_node)
00520 return;
00521
00522 cur_node++;
00523
00524
00525
00526
00527
00528
00529 while(cur_node != nodes.end())
00530 {
00531 cppdom::NodeList::iterator dup_node = (cur_node-1);
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544 if((*cur_node)->isEqual( *dup_node, mIgnoreAttribs, mIgnoreElems))
00545 {
00546 cur_node = nodes.erase(cur_node);
00547 }
00548 else
00549 {
00550 cur_node++;
00551 }
00552
00553 compress_progress += 1;
00554 }
00555
00556
00557 std::cout << std::endl
00558 << "Compression: initial/compressed:" << total_nodes_start << "/" << nodes.size() << std::endl
00559 << " ratio: " << float(nodes.size())/float(total_nodes_start) << std::endl;
00560 }
00561
00562
00563 }
00564