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 CMOOSPlayBackV2 class. 00031 // 00033 #if (_MSC_VER == 1200) 00034 #pragma warning(disable: 4786) 00035 #pragma warning(disable: 4503) 00036 #endif 00037 00038 #include "MOOSPlayBackV2.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 00048 #define MAX_CHOKE_TIME 2.0 00049 00051 // Construction/Destruction 00053 00054 CMOOSPlayBackV2::CMOOSPlayBackV2() 00055 { 00056 m_dfLastMessageTime = 0; 00057 m_nCurrentLine = 0; 00058 m_dfTickTime = 0.01; 00059 m_dfLastClientProcessedTime = -1; 00060 m_bWaitingForClientCatchup = false; 00061 } 00062 00063 CMOOSPlayBackV2::~CMOOSPlayBackV2() 00064 { 00065 00066 } 00067 00068 bool CMOOSPlayBackV2::Initialise(const string &sFileName) 00069 { 00070 00071 if(m_ALog.IsOpen()) 00072 m_ALog.Close(); 00073 00074 00075 m_nCurrentLine = 0; 00076 m_dfLastClientProcessedTime = -1; 00077 m_sFileName = sFileName; 00078 00079 m_ALog.Open(sFileName); 00080 00081 return m_ALog.IsOpen(); 00082 00083 } 00084 00085 bool CMOOSPlayBackV2::IsOpen() 00086 { 00087 return m_ALog.IsOpen(); 00088 } 00089 00090 00091 int CMOOSPlayBackV2::GetSize() 00092 { 00093 return m_ALog.GetLineCount(); 00094 } 00095 00096 double CMOOSPlayBackV2::GetTimeNow() 00097 { 00098 return m_dfLastMessageTime-m_dfLogStart; 00099 } 00100 00101 int CMOOSPlayBackV2::GetCurrentLine() 00102 { 00103 return m_nLastLine; 00104 } 00105 00106 double CMOOSPlayBackV2::GetStartTime() 00107 { 00108 if(!m_ALog.IsOpen() || m_ALog.GetLineCount()<0) 00109 return 0; 00110 00111 return m_ALog.GetEntryTime(0); 00112 00113 } 00114 00115 double CMOOSPlayBackV2::GetFinishTime() 00116 { 00117 if(!m_ALog.IsOpen() || m_ALog.GetLineCount()<0) 00118 return 0; 00119 00120 return m_ALog.GetEntryTime(GetSize()-1); 00121 00122 } 00123 00124 bool CMOOSPlayBackV2::IsEOF() 00125 { 00126 if(!m_ALog.IsOpen()) 00127 return true; 00128 00129 return m_nCurrentLine >= m_ALog.GetLineCount(); 00130 } 00131 00132 00133 bool CMOOSPlayBackV2::Iterate(MOOSMSG_LIST &Output) 00134 { 00135 if(IsEOF()) 00136 return false; 00137 00138 double dfStartTime = m_dfLastMessageTime+1e-6; 00139 double dfStopTime = m_dfLastMessageTime+m_dfTickTime; 00140 00141 bool bDone = false; 00142 00143 while(!bDone && !IsEOF() ) 00144 { 00145 CMOOSMsg NewMsg; 00146 double dfTNext = m_ALog.GetEntryTime(m_nCurrentLine); 00147 00148 00149 //are we in a mode in which we are slaved to a client 00150 //via its publishing of MOOS_CHOKE? 00151 m_dfClientLagTime = MOOSTime() - m_dfLastClientProcessedTime; 00152 if (m_dfLastClientProcessedTime != -1 && 00153 m_dfClientLagTime > MAX_CHOKE_TIME) 00154 { 00155 m_bWaitingForClientCatchup = true; 00156 bDone = true; 00157 dfStopTime = dfTNext; 00158 continue; 00159 } 00160 else 00161 { 00162 //normal sequential processing under our own steam 00163 m_bWaitingForClientCatchup = false; 00164 00165 if(dfTNext<=dfStopTime) 00166 { 00167 00168 if(MessageFromLine(m_ALog.GetLine(m_nCurrentLine),NewMsg)) 00169 { 00170 if(!IsFiltered(NewMsg.GetSource())) 00171 { 00172 Output.push_front(NewMsg); 00173 } 00174 } 00175 00176 00177 // arh moved this out of the loop above, because a failed 00178 // call to MessageFromLine would make uPlayback hang in 00179 // an infinite loop 00180 m_nCurrentLine++; 00181 } 00182 else 00183 { 00184 bDone = true; 00185 } 00186 00187 } 00188 } 00189 00190 //post a playback time 00191 if(!Output.empty()) 00192 { 00193 CMOOSMsg timeMsg( MOOS_NOTIFY, "PLAYBACK_DB_TIME", dfStopTime ); 00194 timeMsg.m_sSrc = "uPlayback"; 00195 Output.push_front( timeMsg ); 00196 } 00197 00198 00199 m_dfLastMessageTime = dfStopTime; 00200 00201 00202 00203 return true; 00204 } 00205 00206 00207 bool CMOOSPlayBackV2::Reset() 00208 { 00209 if(!m_ALog.IsOpen()) 00210 return false; 00211 00212 m_nCurrentLine = 0; 00213 m_dfLastMessageTime = m_ALog.GetEntryTime(0)-1e-6; 00214 00215 return true; 00216 } 00217 00218 bool CMOOSPlayBackV2::SetTickInterval(double dfInterval) 00219 { 00220 m_dfTickTime = dfInterval; 00221 return true; 00222 } 00223 00224 bool CMOOSPlayBackV2::IsFiltered(const std::string & sSrc) 00225 { 00226 return m_SourceFilter.find(sSrc)!=m_SourceFilter.end(); 00227 } 00228 00229 bool CMOOSPlayBackV2::Filter(const std::string & sSrc, bool bWanted) 00230 { 00231 if(bWanted) 00232 { 00233 //remove from our filter things that are wanted 00234 STRING_SET::iterator p = m_SourceFilter.find(sSrc); 00235 00236 if(p!=m_SourceFilter.end()) 00237 { 00238 m_SourceFilter.erase(p); 00239 } 00240 } 00241 else 00242 { 00243 //we don;t want this type of message (from thsinclient) 00244 //so add it to our filter 00245 m_SourceFilter.insert(sSrc); 00246 MOOSTrace("Filtering messages from %s\n",sSrc.c_str()); 00247 } 00248 return true; 00249 } 00250 00251 bool CMOOSPlayBackV2::ClearFilter() 00252 { 00253 m_SourceFilter.clear(); 00254 return true; 00255 } 00256 00257 bool CMOOSPlayBackV2::MessageFromLine(const std::string & sLine, CMOOSMsg &Msg) 00258 { 00259 int n = 0; 00260 std::string sTime,sKey,sSrc; 00261 00262 m_ALog.GetNextToken(sLine,n,sTime); 00263 m_ALog.GetNextToken(sLine,n,sKey); 00264 m_ALog.GetNextToken(sLine,n,sSrc); 00265 00266 size_t nData = sLine.find_first_not_of(" \t",n); 00267 if(nData==string::npos) 00268 return false; 00269 00270 std::string sData = sLine.substr(nData,sLine.size()-nData); 00271 00272 00273 Msg.m_dfTime = MOOSTime(); 00274 00275 if(MOOSIsNumeric(sData)) 00276 { 00277 Msg.m_dfVal = atof(sData.c_str()); 00278 Msg.m_cDataType = MOOS_DOUBLE; 00279 Msg.m_sVal = ""; 00280 } 00281 else 00282 { 00283 Msg.m_dfVal = 0.0; 00284 00285 00286 if(sData.find("<MOOS_BINARY>") !=std::string::npos) 00287 { 00288 //Msg.MarkAsBinary(); 00289 long long nOffset; 00290 if(!MOOSValFromString(nOffset,sData,"Offset")) 00291 return MOOSFail("badly formed MOOS_BINARY indicator - missing \"Offset=xyz\""); 00292 00293 std::string sFile; 00294 if(!MOOSValFromString(sFile,sData,"File")) 00295 return MOOSFail("badly formed MOOS_BINARY indicator - missing \"File=XYZ\""); 00296 00297 int nBytes; 00298 if(!MOOSValFromString(nBytes,sData,"Bytes")) 00299 return MOOSFail("badly formed MOOS_BINARY indicator - missing \"Bytes=xyz\""); 00300 00301 00302 //corner case of binary file changing half way through a log....(Why this might happen 00303 //I don't know but catch it anyway.... 00304 if(sFile != m_sBinaryFileName && m_BinaryFile.is_open() ) 00305 { 00306 m_BinaryFile.close(); 00307 } 00308 m_sBinaryFileName = sFile; 00309 00310 if(!m_BinaryFile.is_open()) 00311 { 00312 //open the file with the correct name 00313 //here we need to point the file towards the full path - the blog file should be sitting next 00314 //to teh alog being played 00315 00317 std::string sPath,sFileName,sExtension; 00318 00319 if(!MOOSFileParts(m_ALog.GetFileName(),sPath,sFileName,sExtension)) 00320 return MOOSFail("failed to parse alog file into file parts %s",MOOSHERE); 00321 00322 std::string sFullBinaryLogPath = sPath+"/"+m_sBinaryFileName; 00323 00324 MOOSTrace("opening binary file %s\n",sFullBinaryLogPath.c_str()); 00325 00326 m_BinaryFile.open(sFullBinaryLogPath.c_str(),std::ios::binary); 00327 if(!m_BinaryFile) 00328 { 00329 return MOOSFail("unable to open binary file called %s", m_sBinaryFileName.c_str()); 00330 } 00331 00332 } 00333 00334 00335 //move to the right place in the file 00336 m_BinaryFile.seekg(nOffset); 00337 00338 //make space 00339 char * pBD = new char[nBytes]; 00340 00341 //read the right number of bytes 00342 m_BinaryFile.read(pBD,nBytes); 00343 00344 //copy data 00345 Msg.m_sVal.assign(pBD,nBytes); 00346 00347 //delete temporary space 00348 delete [] pBD; 00349 00350 Msg.MarkAsBinary(); 00351 00352 00353 00354 } 00355 else 00356 { 00357 Msg.m_dfVal = 0.0; 00358 Msg.m_cDataType = MOOS_STRING; 00359 Msg.m_sVal = sData; 00360 00361 } 00362 00363 } 00364 00365 //fill in standard aspects 00366 Msg.m_sSrc = sSrc; 00367 Msg.m_sKey = sKey; 00368 Msg.m_cMsgType = MOOS_NOTIFY; 00369 00370 00371 return true; 00372 } 00373 00374 double CMOOSPlayBackV2::GetLastMessageTime() 00375 { 00376 return m_dfLastMessageTime; 00377 } 00378 00379 bool CMOOSPlayBackV2::SetLastTimeProcessed(double dfTime) 00380 { 00381 m_dfLastClientProcessedTime = dfTime; 00382 double diff = MOOSTime() - dfTime; 00383 return true; 00384 } 00385 00386 bool CMOOSPlayBackV2::IsWaitingForClient() 00387 { 00388 return m_bWaitingForClientCatchup; 00389 } 00390 00391 string CMOOSPlayBackV2::GetStatusString() 00392 { 00393 return MOOSFormat("%s Client Lag %g", 00394 m_bWaitingForClientCatchup ? "Waiting for Client CATCHUP":"Playing just fine", 00395 m_dfClientLagTime); 00396 } 00397 00398 bool CMOOSPlayBackV2::GotoTime(double dfT) 00399 { 00400 int n = m_ALog.SeekToFindTime(dfT); 00401 00402 if(n!=-1) 00403 { 00404 m_nCurrentLine = n; 00405 m_dfLastClientProcessedTime = -1; 00406 m_bWaitingForClientCatchup = false; 00407 m_dfLastMessageTime = m_ALog.GetEntryTime(m_nCurrentLine)-1e-6; 00408 return true; 00409 } 00410 else 00411 { 00412 return false; 00413 } 00414 }