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 #if (_MSC_VER == 1200) 00031 #pragma warning(disable: 4786) 00032 #pragma warning(disable: 4503) 00033 #endif 00034 00035 #include <MOOSLIB/MOOSLib.h> 00036 00037 #include <FL/Fl_Button.H> 00038 #include <FL/Fl_Clock.H> 00039 #include <FL/Fl_Counter.H> 00040 #include <FL/Fl_File_Chooser.H> 00041 #include <FL/Fl_Check_Browser.H> 00042 #include <FL/Fl_Preferences.H> 00043 #include <FL/filename.H> 00044 #include <FL/fl_ask.H> 00045 #include <FLTKVW/FLTKCheckList.h> 00046 #include <string> 00047 #include "PlaybackWindow.h" 00048 00049 #include <alogTools/indexWriter.h> 00050 00051 #define DEFAULT_COMMS_TICK 40 00052 #define DEFAULT_TIMER_INTERVAL 0.01 00053 #define _USE_32BIT_TIME_T 00054 00055 class CStaticClock : public Fl_Clock 00056 { 00057 private : 00058 typedef Fl_Clock BASE; 00059 public: 00060 CStaticClock( int X, int Y, int W, int H, char *l=0 ) : BASE(X,Y,W,H,l){}; 00061 int handle(int event) 00062 { 00063 switch (event) 00064 { 00065 case FL_SHOW: 00066 return 0; 00067 break; 00068 default: 00069 return BASE::handle(event); 00070 break; 00071 } 00072 } 00073 }; 00074 00075 void GUIRefresh(void* pParam) 00076 { 00077 CPlaybackWindow *pMe = (CPlaybackWindow*)pParam; 00078 pMe->OnGUIRefresh(); 00079 } 00080 00081 CPlaybackWindow::CPlaybackWindow( int X, int Y, int W, int H, const char *l ) : BASE(X,Y,W,H,l) 00082 { 00083 m_dfTimerInterval = DEFAULT_TIMER_INTERVAL; 00084 00085 CStaticClock* pClock = new CStaticClock(20,20,70,70); 00086 pClock->tooltip("playback time"); 00087 SetID(pClock,ID_CLOCK); 00088 pClock->labelsize(10); 00089 pClock->align(FL_ALIGN_TOP); 00090 00091 Fl_Button* pPlayButton = new Fl_Button( 20, 00092 95, 00093 15,15,"@>"); 00094 pPlayButton->labelcolor(FL_GREEN); 00095 SetID(pPlayButton,ID_PLAY); 00096 pPlayButton->tooltip("start playing"); 00097 00098 Fl_Button* pStopButton = new Fl_Button( 37, 00099 95, 00100 15,15,"@-2square"); 00101 pStopButton->labelcolor(FL_RED); 00102 pStopButton->tooltip("stop playing"); 00103 SetID(pStopButton,ID_STOP); 00104 00105 Fl_Button* pRewindButton = new Fl_Button(55, 00106 95, 00107 15,15,"@|<"); 00108 pRewindButton->tooltip("rewind to start"); 00109 SetID(pRewindButton,ID_REWIND); 00110 00111 00112 Fl_Button* pSeekButton = new Fl_Button(73, 00113 00114 95, 00115 00116 15,15,"@-22>"); 00117 00118 pSeekButton->tooltip(" go to seek time"); 00119 00120 SetID(pSeekButton,ID_SEEK); 00121 00122 00123 Fl_Counter* pCounter = new Fl_Counter(20,120,160,20); 00124 pCounter->tooltip(" % progress (adjust to set seek time)"); 00125 SetID(pCounter,ID_PROGRESS); 00126 pCounter->when(FL_WHEN_RELEASE|FL_WHEN_CHANGED); 00127 pCounter->range(0.0,100.0); 00128 pCounter->labelsize(9); 00129 pCounter->align(FL_ALIGN_BOTTOM| FL_ALIGN_LEFT); 00130 pCounter->label("no file loaded"); 00131 00132 00133 pSourceCheck = new Fl_Check_Browser(200,20,120,120,""); 00134 pSourceCheck->tooltip("Select which processes to replay"); 00135 pSourceCheck->align(FL_ALIGN_TOP| FL_ALIGN_LEFT); 00136 pSourceCheck->labelsize(10); 00137 pSourceCheck->label(""); 00138 SetID(pSourceCheck,ID_SOURCE); 00139 00140 00141 Fl_Button* pFileButton = new Fl_Button( 100, 00142 20, 00143 80,20,"File..."); 00144 pFileButton->tooltip("Open *.alog file to replay"); 00145 SetID(pFileButton,ID_FILE); 00146 00147 Fl_Button* pMOOSButton = new Fl_Button( 100, 00148 45, 00149 80,20,"MOOS"); 00150 pMOOSButton->tooltip("Connect to MOOS"); 00151 SetID(pMOOSButton,ID_MOOS); 00152 pMOOSButton->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); 00153 00154 Fl_Button* pConfigureMOOSButton = new Fl_Button( 150, 00155 48, 00156 25,14,"?"); 00157 pConfigureMOOSButton->tooltip("Configure MOOS Connection"); 00158 SetID(pConfigureMOOSButton,ID_MOOS_CONFIGURE); 00159 00160 Fl_Counter* pWarpCounter = new Fl_Counter(100,80,80,20,"warp"); 00161 pWarpCounter->type(FL_SIMPLE_COUNTER); 00162 pWarpCounter->align(FL_ALIGN_TOP); 00163 pWarpCounter->tooltip("alter playback speed"); 00164 SetID(pWarpCounter,ID_WARP); 00165 pWarpCounter->when(FL_WHEN_RELEASE|FL_WHEN_CHANGED); 00166 pWarpCounter->range(0.0,10.0); 00167 pWarpCounter->value(1.0); 00168 00169 //set initial window states 00170 GetByID(ID_PLAY)->deactivate(); 00171 GetByID(ID_STOP)->deactivate(); 00172 GetByID(ID_REWIND)->deactivate(); 00173 GetByID(ID_PROGRESS)->deactivate(); 00174 GetByID(ID_WARP)->deactivate(); 00175 GetByID(ID_SOURCE)->deactivate(); 00176 GetByID(ID_CLOCK)->deactivate(); 00177 00178 //here we read last moos connection info from our preferences 00179 Fl_Preferences app( Fl_Preferences::USER, "MOOS", "uPlayback" ); 00180 char path[ FL_PATH_MAX ]; 00181 app.getUserdataPath( path, sizeof(path) ); 00182 char HostName[FL_PATH_MAX]; 00183 app.get("HostName",HostName,"LOCALHOST",sizeof(HostName)); 00184 int nHost; 00185 app.get("HostPort",nHost,9000); 00186 m_lServerPort = (long)nHost; 00187 m_sServerHost = std::string(HostName); 00188 00189 00190 00191 00192 00193 m_dfSeekTime = 0.0; 00194 00195 00196 //here we add a timer to keep thinsg refreshed 00197 //this fixes a problem with some guio stuff happening outside thread 0 00198 Fl::add_timeout(0.25,GUIRefresh,this); 00199 00200 m_eMode = STOPPED; 00201 } 00202 00203 void CPlaybackWindow::OnGUIRefresh() 00204 { 00205 ManageWidgetStates(); 00206 SetTitle(); 00207 Fl::redraw(); 00208 Fl::add_timeout(0.25,GUIRefresh,this); 00209 } 00210 void CPlaybackWindow::OnControlWidget(Fl_Widget* pWidget,int ID) 00211 { 00212 //this is the swicth yard for all messages 00213 switch(ID) 00214 { 00215 case ID_PLAY: 00216 OnPlayButton(); 00217 ShowProgress(); 00218 m_eMode = PLAYING; 00219 break; 00220 case ID_STOP: 00221 OnStopButton(); 00222 m_eMode = STOPPED; 00223 break; 00224 case ID_MOOS: 00225 OnMOOS(); 00226 GetByID(ID_MOOS_CONFIGURE)->take_focus(); 00227 break; 00228 case ID_REWIND: 00229 StopTimer(); 00230 m_PlayBack.Reset(); 00231 00232 m_eMode = STOPPED; 00233 ShowProgress(); 00234 break; 00235 case ID_WARP: 00236 OnWarp(); 00237 break; 00238 case ID_FILE: 00239 OnFile(); 00240 m_PlayBack.Reset(); 00241 ShowProgress(); 00242 break; 00243 00244 case ID_SEEK: 00245 00246 StopTimer(); 00247 00248 m_eMode = STOPPED; 00249 00250 m_PlayBack.Reset(); 00251 00252 m_PlayBack.GotoTime(m_dfSeekTime); 00253 00254 ShowProgress(); 00255 00256 break; 00257 case ID_PROGRESS: 00258 OnProgress(); 00259 break; 00260 case ID_MOOS_CONFIGURE: 00261 OnMOOSConfigure(); 00262 break; 00263 } 00264 00265 ManageWidgetStates(); 00266 00267 } 00268 bool CPlaybackWindow::OnMOOSConfigure() 00269 { 00270 //ask the user wher he/she wants to connect to 00271 const char * scHost=fl_input("MOOSDB Host Name", m_sServerHost.c_str()); 00272 if(scHost==NULL) 00273 return false; 00274 m_sServerHost = std::string(scHost); 00275 00276 std::string sPort = MOOSFormat("%d",(int)m_lServerPort); 00277 const char * scPort=fl_input("MOOSDB Port", sPort.c_str()); 00278 if(scPort==NULL) 00279 return false; 00280 m_lServerPort = atol(scPort); 00281 SetTitle(); 00282 return true; 00283 } 00284 00285 bool CPlaybackWindow::SetTitle(bool bOnline) 00286 { 00287 Fl_Window* p = GetRootWindow(); 00288 00289 static char sTitle[1024]; 00290 sprintf(sTitle,"uPlayback : %s:%d %s",m_sServerHost.c_str(),(int)m_lServerPort,m_Comms.IsConnected()|| bOnline ? "Online":"Offline"); 00291 p->label(sTitle); 00292 p->labelcolor(FL_RED); 00293 return true; 00294 } 00295 00296 bool CPlaybackWindow::ManageWidgetStates() 00297 { 00298 if(m_Comms.IsConnected()) 00299 { 00300 GetByID(ID_MOOS)->deactivate(); 00301 if(m_PlayBack.IsOpen()) 00302 { 00303 GetByID(ID_CLOCK)->activate(); 00304 GetByID(ID_REWIND)->activate(); 00305 GetByID(ID_PROGRESS)->activate(); 00306 GetByID(ID_WARP)->activate(); 00307 GetByID(ID_MOOS)->deactivate(); 00308 if(m_eMode == PLAYING) 00309 { 00310 GetByID(ID_PLAY)->deactivate(); 00311 GetByID(ID_STOP)->activate(); 00312 } 00313 else if(m_eMode == STOPPED) 00314 { 00315 GetByID(ID_PLAY)->activate(); 00316 GetByID(ID_STOP)->deactivate(); 00317 } 00318 } 00319 else 00320 { 00321 GetByID(ID_CLOCK)->deactivate(); 00322 } 00323 } 00324 return true; 00325 } 00326 00327 bool CPlaybackWindow::OnProgress() 00328 { 00329 if(Fl::event()&FL_RELEASE) 00330 { 00331 double dfPC = ((Fl_Counter*)GetByID(ID_PROGRESS))->value(); 00332 double dfDuration = m_PlayBack.GetFinishTime()-m_PlayBack.GetStartTime(); 00333 double dfT = m_PlayBack.GetStartTime()+dfPC/100.0*dfDuration; 00334 ((Fl_Clock*)GetByID(ID_CLOCK))->value((int)dfT); 00335 m_dfSeekTime = dfT; 00336 return m_PlayBack.GotoTime(dfT); 00337 } 00338 else 00339 { 00340 StopTimer(); 00341 } 00342 return true; 00343 00344 } 00345 bool CPlaybackWindow::OnWarp() 00346 { 00347 if(Fl::event()&FL_RELEASE) 00348 { 00349 double dfWarp = ((Fl_Counter*)GetByID(ID_WARP))->value(); 00350 m_PlayBack.SetTickInterval(dfWarp*m_dfTimerInterval); 00351 } 00352 return true; 00353 } 00354 00355 bool CPlaybackWindow::OnFile() 00356 { 00357 //here we try to recall the last file we opened 00358 Fl_Preferences app( Fl_Preferences::USER, "MOOS", "uPlayback" ); 00359 00360 char path[ FL_PATH_MAX ]; 00361 app.getUserdataPath( path, sizeof(path) ); 00362 00363 char LastFile[FL_PATH_MAX]; 00364 app.get("LastFile",LastFile,"*",sizeof(LastFile)); 00365 00366 const char * pFile = fl_file_chooser("Select an alog file", "*.alog", LastFile); 00367 00368 bool bInitialised = false; 00369 if(pFile) 00370 { 00371 //CWaitCursor Cursor; 00372 GetRootWindow()->cursor(FL_CURSOR_WAIT ); 00373 00374 GetByID(ID_PROGRESS)->label("LOADING AND PARSING ALOG...PLEASE WAIT"); 00375 00376 redraw(); 00377 00378 Fl::wait(); 00379 00380 while (!bInitialised) 00381 { 00382 if(m_PlayBack.Initialise(pFile)) 00383 { 00384 m_sFileName = std::string(pFile); 00385 pSourceCheck->clear(); 00386 00387 STRING_SET Sources = m_PlayBack.GetSources(); 00388 STRING_SET::iterator p; 00389 int i =0; 00390 for(p = Sources.begin();p!= Sources.end();p++) 00391 { 00392 pSourceCheck->add(p->c_str(),1); 00393 } 00394 00395 GetByID(ID_SOURCE)->activate(); 00396 GetByID(ID_CLOCK)->activate(); 00397 00398 //here we save the last file we opened 00399 app.set( "LastFile",pFile ); 00400 00401 GetByID(ID_PROGRESS)->label(pFile); 00402 00403 //lets tell the user how much data has been loaded 00404 static char sNumRecords[128]; 00405 sprintf(sNumRecords,"%d records",m_PlayBack.m_ALog.GetLineCount()); 00406 GetByID(ID_SOURCE)->label(sNumRecords); 00407 00408 bInitialised = true; 00409 } 00410 else 00411 { 00412 int v = fl_choice("Cannot find index file for this alog. Would you like to create one?", 00413 "No", "Yes", NULL); 00414 00415 if (v == 0) 00416 break; 00417 else 00418 { 00419 indexWriter idxWriter; 00420 idxWriter.parseAlogFile(string(pFile)); 00421 idxWriter.writeIndexFile(string(pFile)+string(".idx")); 00422 } 00423 00424 } 00425 00426 } 00427 00428 GetRootWindow()->cursor(FL_CURSOR_DEFAULT ); 00429 } 00430 00431 take_focus(); 00432 return bInitialised; 00433 } 00434 00435 Fl_Window * CPlaybackWindow::GetRootWindow() 00436 { 00437 Fl_Widget * p=this; 00438 while(1) 00439 { 00440 if(p->parent()==NULL) 00441 return (Fl_Window *)p; 00442 else 00443 p = p->parent(); 00444 } 00445 } 00446 00447 bool CPlaybackWindow::OnMOOS() 00448 { 00449 00450 if(m_Comms.IsConnected()) 00451 { 00452 m_Comms.Close(); 00453 } 00454 00455 //next line is pretty crucial... 00456 m_Comms.FakeSource(true); 00457 m_Comms.SetOnConnectCallBack(MOOSConnectCallBack,(void*)this); 00458 m_Comms.SetOnDisconnectCallBack(MOOSDisconnectCallBack,(void*)this); 00459 00460 //here we try to 00461 Fl_Preferences app( Fl_Preferences::USER, "MOOS", "uPlayback" ); 00462 app.set("HostName",m_sServerHost.c_str()); 00463 app.set("HostPort",(int)(m_lServerPort)); 00464 00465 return m_Comms.Run(m_sServerHost.c_str(),m_lServerPort,"uPlayback",DEFAULT_COMMS_TICK); 00466 } 00467 00468 bool CPlaybackWindow::OnMOOSDisconnect() 00469 { 00470 SetTitle(); 00471 return true; 00472 } 00473 00474 00475 bool CPlaybackWindow::OnMOOSConnect() 00476 { 00477 SetTitle(); 00478 redraw(); 00479 return true; 00480 } 00481 00482 00483 bool CPlaybackWindow::OnPlayButton() 00484 { 00485 MakeMessageFilter(); 00486 m_nTimerHits = 0; 00487 00488 StartTimer(m_dfTimerInterval); 00489 00490 return true; 00491 } 00492 bool CPlaybackWindow::OnNewMail(MOOSMSG_LIST &NewMail) 00493 { 00494 00495 CMOOSMsg Msg; 00496 if (m_Comms.PeekMail(NewMail,"PLAYBACK_CHOKE",Msg)) 00497 { 00498 double dfLastTimeProcessed = Msg.m_dfVal; 00499 m_PlayBack.SetLastTimeProcessed(dfLastTimeProcessed); 00500 } 00501 00502 return true; 00503 } 00504 00505 bool CPlaybackWindow::OnStopButton() 00506 { 00507 StopTimer(); 00508 return true; 00509 } 00510 00511 00512 void CPlaybackWindow::OnTimer() 00513 { 00514 if (m_Comms.IsConnected()) 00515 { 00516 MOOSMSG_LIST NewMail; 00517 if(m_Comms.Fetch(NewMail)) 00518 { 00519 OnNewMail(NewMail); 00520 } 00521 } 00522 00523 MOOSMSG_LIST Output; 00524 00525 if(m_PlayBack.Iterate(Output)) 00526 { 00527 MOOSMSG_LIST::iterator p; 00528 00529 for(p = Output.begin();p!=Output.end();p++) 00530 { 00531 CMOOSMsg & rMsg = *p; 00532 00533 if(m_Comms.IsConnected()) 00534 { 00535 m_Comms.Post(rMsg); 00536 } 00537 } 00538 } 00539 else 00540 { 00541 if(m_PlayBack.IsEOF()) 00542 { 00543 OnStopButton(); 00544 } 00545 } 00546 00547 if((m_nTimerHits++)%25==0) 00548 { 00549 ShowProgress(); 00550 } 00551 00552 } 00553 00554 bool CPlaybackWindow::ShowProgress() 00555 { 00556 //show percent elapsed 00557 double dfProgress =0; 00558 double dfDuration = m_PlayBack.GetFinishTime()-m_PlayBack.GetStartTime(); 00559 double dfElapsed = m_PlayBack.GetLastMessageTime()-m_PlayBack.GetStartTime(); 00560 00561 ((Fl_Clock*)GetByID(ID_CLOCK))->value((int)m_PlayBack.GetLastMessageTime()); 00562 if(1 || dfElapsed>=0) 00563 { 00564 dfProgress = 100.0*(dfElapsed)/(dfDuration); 00565 ((Fl_Counter*)GetByID(ID_PROGRESS))->value(dfProgress); 00566 } 00567 Fl_Clock* pClock = (Fl_Clock*)GetByID(ID_CLOCK); 00568 00569 static char Time[256]; 00570 sprintf(Time,"%.2d:%.2d.%.2d",pClock->hour(),pClock->minute(),pClock->second()); 00571 pClock->label(Time); 00572 00573 00574 return true; 00575 } 00576 00577 00578 bool CPlaybackWindow::MakeMessageFilter() 00579 { 00580 m_PlayBack.ClearFilter(); 00581 00582 for(int i = 0;i<=pSourceCheck->nitems();i++) 00583 { 00584 char * pText = pSourceCheck->text(i); 00585 if(pText!=NULL) 00586 { 00587 std::string sSrc(pText); 00588 bool bWanted = pSourceCheck->checked(i)?true:false; 00589 m_PlayBack.Filter(sSrc,bWanted); 00590 } 00591 } 00592 00593 return true; 00594 } 00595 00596