MOOS 0.2375
|
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 }