MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/Tools/Graphical/uIndexedPlayBack/MOOSPlayBackIndex.cpp
Go to the documentation of this file.
00001 
00002 //
00003 //   MOOS - Mission Oriented Operating Suite 
00004 //  
00005 //   A suit of Applications and Libraries for Mobile Robotics Research 
00006 //   Copyright (C) 2001-2005 Massachusetts Institute of Technology and 
00007 //   Oxford University. 
00008 //    
00009 //   This software was written by Paul Newman at MIT 2001-2002 and Oxford 
00010 //   University 2003-2005. email: pnewman@robots.ox.ac.uk. 
00011 //      
00012 //   This file is part of a  MOOS Utility Component. 
00013 //        
00014 //   This program is free software; you can redistribute it and/or 
00015 //   modify it under the terms of the GNU General Public License as 
00016 //   published by the Free Software Foundation; either version 2 of the 
00017 //   License, or (at your option) any later version. 
00018 //          
00019 //   This program is distributed in the hope that it will be useful, 
00020 //   but WITHOUT ANY WARRANTY; without even the implied warranty of 
00021 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
00022 //   General Public License for more details. 
00023 //            
00024 //   You should have received a copy of the GNU General Public License 
00025 //   along with this program; if not, write to the Free Software 
00026 //   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 
00027 //   02111-1307, USA. 
00028 //
00030 // MOOSPlayBack.cpp: implementation of the CMOOSPlayBackIndex class.
00031 //
00033 #if (_MSC_VER == 1200)
00034 #pragma warning(disable: 4786)
00035 #pragma warning(disable: 4503)
00036 #endif
00037 
00038 #include "MOOSPlayBackIndex.h"
00039 #include <algorithm>
00040 
00041 #ifdef _DEBUG
00042 #undef THIS_FILE
00043 static char THIS_FILE[]=__FILE__;
00044 #define new DEBUG_NEW
00045 #endif
00046 
00047 #define MAX_CHOKE_TIME 2.0
00048 
00050 // Construction/Destruction
00052 
00053 CMOOSPlayBackIndex::CMOOSPlayBackIndex()
00054 {
00055     m_dfLastMessageTime = 0;
00056     m_nCurrentLine = 0;
00057     m_dfTickTime = 0.01;
00058     m_dfLastClientProcessedTime = -1;
00059     m_bWaitingForClientCatchup = false;
00060 }
00061 
00062 CMOOSPlayBackIndex::~CMOOSPlayBackIndex()
00063 {
00064 
00065 }
00066 
00067 bool CMOOSPlayBackIndex::Initialise(const string &sFileName)
00068 {
00069     if (m_ALog.IsOpen())
00070         m_ALog.Close();
00071 
00072     m_nCurrentLine = 0;
00073     m_dfLastClientProcessedTime = -1;
00074     m_sFileName = sFileName;
00075 
00076     return m_ALog.Open(sFileName);
00077 }
00078 
00079 bool CMOOSPlayBackIndex::IsOpen()
00080 {
00081     return m_ALog.IsOpen();
00082 }
00083 
00084 int CMOOSPlayBackIndex::GetSize()
00085 {
00086     return m_ALog.GetLineCount();
00087 }
00088 
00089 double CMOOSPlayBackIndex::GetTimeNow()
00090 {
00091     return m_dfLastMessageTime - m_dfLogStart;
00092 }
00093 
00094 int CMOOSPlayBackIndex::GetCurrentLine()
00095 {
00096     return m_nLastLine;
00097 }
00098 
00099 double CMOOSPlayBackIndex::GetStartTime()
00100 {
00101     if (!m_ALog.IsOpen() || m_ALog.GetLineCount() < 0)
00102         return 0;
00103 
00104     return m_ALog.GetEntryTime(0);
00105 
00106 }
00107 
00108 double CMOOSPlayBackIndex::GetFinishTime()
00109 {
00110     if (!m_ALog.IsOpen() || m_ALog.GetLineCount() < 0)
00111         return 0;
00112 
00113     return m_ALog.GetEntryTime(GetSize() - 1);
00114 
00115 }
00116 
00117 bool CMOOSPlayBackIndex::IsEOF()
00118 {
00119     if (!m_ALog.IsOpen())
00120         return true;
00121 
00122     return m_nCurrentLine >= m_ALog.GetLineCount();
00123 }
00124 
00125 bool CMOOSPlayBackIndex::Iterate(MOOSMSG_LIST &Output)
00126 {
00127     if (IsEOF())
00128         return false;
00129 
00130     double dfStopTime = m_dfLastMessageTime + m_dfTickTime;
00131 
00132     bool bDone = false;
00133 
00134     while (!bDone && !IsEOF())
00135     {
00136         CMOOSMsg NewMsg;
00137 
00138         double dfTNext = m_ALog.GetEntryTime(m_nCurrentLine);
00139 
00140         //are we in a mode in which we are slaved to a client
00141         //via its publishing of MOOS_CHOKE?
00142         m_dfClientLagTime = MOOSTime() - m_dfLastClientProcessedTime;
00143         if (m_dfLastClientProcessedTime != -1 && m_dfClientLagTime
00144                 > MAX_CHOKE_TIME)
00145         {
00146             m_bWaitingForClientCatchup = true;
00147             bDone = true;
00148             dfStopTime = dfTNext;
00149             continue;
00150         } else
00151         {
00152             //normal sequential processing under our own steam
00153             m_bWaitingForClientCatchup = false;
00154 
00155             if (dfTNext <= dfStopTime)
00156             {
00157 
00158                 if (MessageFromLine(m_ALog.GetLine(m_nCurrentLine), NewMsg))
00159                 {
00160                     if (!IsFiltered(NewMsg.GetSource()))
00161                     {
00162                         Output.push_front(NewMsg);
00163                     }
00164                 }
00165 
00166                 CMOOSMsg timeMsg(MOOS_NOTIFY, "PLAYBACK_DB_TIME", dfTNext,
00167                         dfTNext);
00168                 Output.push_front(timeMsg);
00169 
00170                 // arh moved this out of the loop above, because a failed
00171                 // call to MessageFromLine would make uPlayback hang in
00172                 // an infinite loop
00173                 m_nCurrentLine++;
00174             } else
00175             {
00176                 bDone = true;
00177             }
00178 
00179         }
00180     }
00181 
00182     m_dfLastMessageTime = dfStopTime;
00183 
00184     return true;
00185 }
00186 
00187 bool CMOOSPlayBackIndex::Reset()
00188 {
00189     if (!m_ALog.IsOpen())
00190         return false;
00191 
00192     m_nCurrentLine = 0;
00193     m_dfLastMessageTime = m_ALog.GetEntryTime(0) - 1e-6;
00194 
00195     return true;
00196 }
00197 
00198 bool CMOOSPlayBackIndex::SetTickInterval(double dfInterval)
00199 {
00200     m_dfTickTime = dfInterval;
00201     return true;
00202 }
00203 
00204 bool CMOOSPlayBackIndex::IsFiltered(const std::string & sSrc)
00205 {
00206     return m_SourceFilter.find(sSrc) != m_SourceFilter.end();
00207 }
00208 
00209 bool CMOOSPlayBackIndex::Filter(const std::string & sSrc, bool bWanted)
00210 {
00211     if (bWanted)
00212     {
00213         //remove from our filter things that are wanted
00214         STRING_SET::iterator p = m_SourceFilter.find(sSrc);
00215 
00216         if (p != m_SourceFilter.end())
00217         {
00218             m_SourceFilter.erase(p);
00219         }
00220     } else
00221     {
00222         //we don;t want this type of message (from thsinclient)
00223         //so add it to our filter
00224         m_SourceFilter.insert(sSrc);
00225         MOOSTrace("Filtering messages from %s\n", sSrc.c_str());
00226     }
00227     return true;
00228 }
00229 
00230 bool CMOOSPlayBackIndex::ClearFilter()
00231 {
00232     m_SourceFilter.clear();
00233     return true;
00234 }
00235 
00236 bool CMOOSPlayBackIndex::MessageFromLine(const std::string & sLine,
00237         CMOOSMsg &Msg)
00238 {
00239     int n = 0;
00240     std::string sTime, sKey, sSrc;
00241 
00242     m_ALog.GetNextToken(sLine, n, sTime);
00243     m_ALog.GetNextToken(sLine, n, sKey);
00244     m_ALog.GetNextToken(sLine, n, sSrc);
00245 
00246     // this needs to be size_t and _not_ unsigned int to avoid segfaults on
00247     // 64-bit machines: size_t is 64-bit, unsigned int is 32-bit
00248     size_t nData = sLine.find_first_not_of(" \t", n);
00249     if (nData == string::npos)
00250         return false;
00251 
00252     std::string sData = sLine.substr(nData, sLine.size() - nData);
00253 
00254     Msg.m_dfTime = MOOSTime();
00255 
00256     if (MOOSIsNumeric(sData))
00257     {
00258         Msg.m_dfVal = atof(sData.c_str());
00259         Msg.m_cDataType = MOOS_DOUBLE;
00260         Msg.m_sVal = "";
00261     }
00262     else
00263     {
00264         Msg.m_dfVal = 0.0;
00265 
00266         if (sData.find("<MOOS_BINARY>") != std::string::npos)
00267         {
00268             //Msg.MarkAsBinary();
00269             long long nOffset;
00270             if (!MOOSValFromString(nOffset, sData, "Offset"))
00271                 return MOOSFail(
00272                         "badly formed MOOS_BINARY indicator - missing \"Offset=xyz\"");
00273 
00274             std::string sFile;
00275             if (!MOOSValFromString(sFile, sData, "File"))
00276                 return MOOSFail(
00277                         "badly formed MOOS_BINARY indicator - missing \"File=XYZ\"");
00278 
00279             int nBytes;
00280             if (!MOOSValFromString(nBytes, sData, "Bytes"))
00281                 return MOOSFail(
00282                         "badly formed MOOS_BINARY indicator - missing \"Bytes=xyz\"");
00283 
00284             //corner case of binary file changing half way through a log....(Why this might happen
00285             //I don't know but catch it anyway....
00286             if (sFile != m_sBinaryFileName && m_BinaryFile.is_open())
00287             {
00288                 m_BinaryFile.close();
00289             }
00290             m_sBinaryFileName = sFile;
00291 
00292             if (!m_BinaryFile.is_open())
00293             {
00294                 //open the file with the correct name
00295                 //here we need to point the file towards the full path - the blog file should be sitting next
00296                 //to teh alog being played
00297 
00299                 std::string sPath, sFileName, sExtension;
00300 
00301                 if (!MOOSFileParts(m_ALog.GetFileName(), sPath, sFileName,
00302                         sExtension))
00303                     return MOOSFail(
00304                             "failed to parse alog file into file parts %s",
00305                             MOOSHERE);
00306 
00307                 std::string sFullBinaryLogPath = sPath + "/"
00308                         + m_sBinaryFileName;
00309 
00310                 MOOSTrace("opening binary file %s\n",
00311                         sFullBinaryLogPath.c_str());
00312 
00313                 m_BinaryFile.open(sFullBinaryLogPath.c_str(), std::ios::binary);
00314                 if (!m_BinaryFile)
00315                 {
00316                     return MOOSFail("unable to open binary file called %s",
00317                             m_sBinaryFileName.c_str());
00318                 }
00319 
00320             }
00321 
00322             //move to the right place in the file
00323             m_BinaryFile.seekg(nOffset);
00324 
00325             //make space
00326             char * pBD = new char[nBytes];
00327 
00328             //read the right number of bytes
00329             m_BinaryFile.read(pBD, nBytes);
00330 
00331             //copy data
00332             Msg.m_sVal.assign(pBD, nBytes);
00333 
00334             //delete temporary space
00335             delete[] pBD;
00336 
00337             Msg.MarkAsBinary();
00338 
00339         } else
00340         {
00341             Msg.m_dfVal = 0.0;
00342             Msg.m_cDataType = MOOS_STRING;
00343             Msg.m_sVal = sData;
00344 
00345         }
00346 
00347     }
00348 
00349     Msg.m_sSrc = sSrc;
00350     Msg.m_sKey = sKey;
00351     Msg.m_cMsgType = MOOS_NOTIFY;
00352 
00353     return true;
00354 }
00355 
00356 double CMOOSPlayBackIndex::GetLastMessageTime()
00357 {
00358     return m_dfLastMessageTime;
00359 }
00360 
00361 bool CMOOSPlayBackIndex::SetLastTimeProcessed(double dfTime)
00362 {
00363     m_dfLastClientProcessedTime = dfTime;
00364     //double diff = MOOSTime() - dfTime;
00365     return true;
00366 }
00367 
00368 bool CMOOSPlayBackIndex::IsWaitingForClient()
00369 {
00370     return m_bWaitingForClientCatchup;
00371 }
00372 
00373 string CMOOSPlayBackIndex::GetStatusString()
00374 {
00375     return MOOSFormat("%s Client Lag %g",
00376             m_bWaitingForClientCatchup ? "Waiting for Client CATCHUP"
00377                     : "Playing just fine", m_dfClientLagTime);
00378 }
00379 
00380 bool CMOOSPlayBackIndex::GotoTime(double dfT)
00381 {
00382     int n = m_ALog.SeekToFindTime(dfT);
00383 
00384     if (n != -1)
00385     {
00386         m_nCurrentLine = n;
00387         m_dfLastClientProcessedTime = -1;
00388         m_bWaitingForClientCatchup = false;
00389         m_dfLastMessageTime = m_ALog.GetEntryTime(m_nCurrentLine) - 1e-6;
00390         return true;
00391     } else
00392     {
00393         return false;
00394     }
00395 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines