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 and others 00010 // at MIT 2001-2002 and Oxford University 2003-2005. 00011 // email: pnewman@robots.ox.ac.uk. 00012 // 00013 // This file is part of a MOOS Instrument. 00014 // 00015 // This program is free software; you can redistribute it and/or 00016 // modify it under the terms of the GNU General Public License as 00017 // published by the Free Software Foundation; either version 2 of the 00018 // License, or (at your option) any later version. 00019 // 00020 // This program is distributed in the hope that it will be useful, 00021 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00023 // General Public License for more details. 00024 // 00025 // You should have received a copy of the GNU General Public License 00026 // along with this program; if not, write to the Free Software 00027 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 00028 // 02111-1307, USA. 00029 // 00031 // ADVInstrument.cpp: implementation of the CADVInstrument class. 00032 // 00034 #include <MOOSLIB/MOOSLib.h> 00035 #include <iostream> 00036 using namespace std; 00037 00038 #include "ADVInstrument.h" 00039 00041 // Construction/Destruction 00043 00044 CADVInstrument::CADVInstrument() 00045 { 00046 //some sensible defaults (missionfile can overwrite this) 00047 SetAppFreq(10); 00048 SetCommsFreq(10); 00049 00050 } 00051 00052 CADVInstrument::~CADVInstrument() 00053 { 00054 00055 } 00056 00059 bool CADVInstrument::Iterate() 00060 { 00061 00062 if(GetData()) 00063 { 00064 PublishData(); 00065 } 00066 00067 return true; 00068 } 00069 00070 00071 bool CADVInstrument::OnStartUp() 00072 { 00073 CMOOSInstrument::OnStartUp(); 00074 00075 //here we make the variables that we are managing 00076 double dfADVPeriod = 0.2; 00077 //ADV Referenced Velocity 00078 AddMOOSVariable("VEL_X", "", "ADV_X", dfADVPeriod); 00079 AddMOOSVariable("VEL_Y", "", "ADV_Y", dfADVPeriod); 00080 AddMOOSVariable("VEL_Z", "", "ADV_Z", dfADVPeriod); 00081 AddMOOSVariable("VEL_SAMPLE_NO","", "ADV_SAMPLE", dfADVPeriod); 00082 00083 //Amplitudes 00084 AddMOOSVariable("AMP_1", "", "ADV_AMP_1", dfADVPeriod); 00085 AddMOOSVariable("AMP_2", "", "ADV_AMP_2", dfADVPeriod); 00086 AddMOOSVariable("AMP_3", "", "ADV_AMP_3", dfADVPeriod); 00087 00088 //Correlation 00089 AddMOOSVariable("COR_1", "", "ADV_COR_1", dfADVPeriod); 00090 AddMOOSVariable("COR_2", "", "ADV_COR_2", dfADVPeriod); 00091 AddMOOSVariable("COR_3", "", "ADV_COR_3", dfADVPeriod); 00092 00093 //Register for the variable that will provide for dynamic configuration 00094 //of the ADV 00095 AddMOOSVariable("UPDATE_CMD", "ADV_UPDATE", "ADV_UPDATE_REPLY", dfADVPeriod); 00096 00097 RegisterMOOSVariables(); 00098 00099 //use the *pfn callback routine in the SerialPort to notify that we are interested 00100 //in using the prompt given back to us by the ADV 00101 //Error Message for Unrecognized Command: ERROR: Command not recognized: DGS 00102 //Common to error message strings is ERROR 00103 00104 SetPrompt(">"); 00105 SetInstrumentErrorMessage("ERROR"); 00106 00107 if(IsSimulateMode()) 00108 { 00109 SetAppFreq(10); 00110 SetCommsFreq(8); 00111 } 00112 else 00113 { 00114 00115 //try to open 00116 if(!SetupPort()) 00117 { 00118 return false; 00119 } 00120 00121 //try 10 times to initialise sensor 00122 if(!InitialiseSensorN(10,"ADV")) 00123 { 00124 return false; 00125 } 00126 00127 } 00128 return true; 00129 } 00130 00131 00132 00133 bool CADVInstrument::OnNewMail(MOOSMSG_LIST &NewMail) 00134 { 00135 CMOOSMsg Msg; 00136 double dfTimeNow = MOOSTime(); 00137 00138 if(m_Comms.PeekMail(NewMail,"ADV_UPDATE",Msg)) 00139 { 00140 MOOSTrace("..............new ADV_UPDATE: %s\n", Msg.m_sVal.c_str()); 00141 return ExecuteADVUpdateCommands(Msg); 00142 } 00143 else 00144 { 00145 return UpdateMOOSVariables(NewMail); 00146 } 00147 } 00148 00149 bool CADVInstrument::PublishData() 00150 { 00151 return PublishFreshMOOSVariables(); 00152 } 00153 00154 00155 00156 bool CADVInstrument::OnConnectToServer() 00157 { 00158 if(IsSimulateMode()) 00159 { 00160 RegisterMOOSVariables(); 00161 } 00162 return true; 00163 } 00164 00165 00167 // here we initialise the sensor, giving it start up values 00168 bool CADVInstrument::InitialiseSensor() 00169 { 00170 #define MAXTRIES 10 00171 int nTries = 0; 00172 00173 TERMPAIRLIST InitCmds; 00174 00175 //STRING_LIST sInitCmds; 00176 00177 //The ADV replies with a '>' prompt 00178 m_Port.SetTermCharacter(m_sPrompt.c_str()[0]); 00179 00180 //Wake up the sensor 00181 m_Port.Break(); 00182 MOOSPause(1000); 00183 00184 InitCmds.push_back(SendTermPair("OF ASCII\r",m_sPrompt.c_str())); 00185 InitCmds.push_back(SendTermPair("VR 4\r",m_sPrompt)); 00186 InitCmds.push_back(SendTermPair("SR 3.0\r",m_sPrompt.c_str())); 00187 InitCmds.push_back(SendTermPair("Start\r",m_sPrompt.c_str())); 00188 00189 00190 TERMPAIRLIST::iterator p; 00191 00192 string sWhatReply; 00193 00194 double dfWhen; 00195 00196 for(p = InitCmds.begin(); p != InitCmds.end(); p) 00197 { 00198 SendTermPair & rToDo = *p; 00199 //string sCmd = *p; 00200 00201 //make sure to pause before reading the reply 00202 //@9600bps, ADV may not react fast enough 00203 MOOSPause(500); 00204 00205 while(!m_Port.GetLatest(sWhatReply,dfWhen)) 00206 { 00207 MOOSPause(10); 00208 } 00209 00210 //check reply... 00211 //if(GoodReply(sCmd, sWhatReply)) 00212 if(GoodReply(sWhatReply)) 00213 { 00214 m_Port.Write((char *)rToDo.sSend.c_str(),rToDo.sSend.size()); 00215 p++; 00216 00217 } 00218 else 00219 { 00220 MOOSTrace("D'oh!\n"); 00221 if(nTries++ > MAXTRIES) 00222 return false; 00223 } 00224 00225 00226 } 00227 00228 //Need to put the device back in a mode where it looks for <CR> 00229 //to delimit a Telegram 00230 m_Port.SetTermCharacter('\r'); 00231 00232 return true; 00233 } 00234 00235 00243 bool CADVInstrument::GetData() 00244 { 00245 if(!IsSimulateMode()) 00246 { 00247 //here we actually access serial ports etc 00248 string sWhat; 00249 double dfWhen; 00250 00251 if(m_Port.IsStreaming()) 00252 { 00253 if(!m_Port.GetLatest(sWhat,dfWhen)) 00254 { 00255 00256 return false; 00257 } 00258 } 00259 else 00260 { 00261 MOOSTrace("ADV Must be streaming..\n"); 00262 00263 return false; 00264 00265 } 00266 00267 00268 ParseADVReply(sWhat); 00269 00270 00271 } 00272 else 00273 { 00274 //in simulated mode there is nothing to do..all data 00275 //arrives via comms. 00276 } 00277 00278 return true; 00279 00280 } 00281 00282 00283 bool CADVInstrument::GoodReply(string sReply) 00284 { 00285 char * pPrompt = NULL; 00286 char * pError = NULL; 00287 00288 //look for the prompt and an error 00289 //keep track of where each resides 00290 pPrompt = strstr(sReply.c_str(), m_sPrompt.c_str()); 00291 pError = strstr(sReply.c_str(), m_sInstrumentErrorMessage.c_str()); 00292 00293 if((pError != NULL) && (pPrompt != NULL)) 00294 return false; 00295 else if((pError != NULL) && (pPrompt == NULL)) 00296 return false; 00297 else if((pError == NULL) && (pPrompt == NULL)) 00298 return false; 00299 else 00300 return true; 00301 00302 } 00303 00304 bool CADVInstrument::ExecuteADVUpdateCommands(CMOOSMsg &Msg) 00305 { 00306 #define FRESH_UPDATE 30.0 00307 string sCmdUpdateStatus; 00308 double dfTimeNow = MOOSTime(); 00309 00310 //only interested in the string message of comma separated 00311 //values for the ADV. 00312 string sNewCmdString = Msg.m_sVal; 00313 MOOSTrace("Update ADV: Cmd - [%s] - Size - %d \n", sNewCmdString.c_str(), sNewCmdString.size()); 00314 00315 //check for skewedness 00316 if(NewCommandsAreSkewed(Msg, dfTimeNow, sNewCmdString)) 00317 return false; 00318 00319 //Stop the ADV from streaming and get it's attention 00320 if(!GetADVAttention()) 00321 return false; 00322 00323 //send the commands 00324 if(SendADVUpdatedCommands(sCmdUpdateStatus, sNewCmdString)) 00325 { 00326 //Set the UPDATE_ADV_REPLY variable to indicate success 00327 MOOSTrace("Update ADV: Pinging Restarted\n"); 00328 SetMOOSVar("UPDATE_CMD", sCmdUpdateStatus, dfTimeNow); 00329 00330 //reset the Termination character 00331 m_Port.SetTermCharacter('\r'); 00332 00333 //start the sensor pinging again 00334 StartPinging(); 00335 00336 } 00337 else 00338 { 00339 MOOSTrace("Update ADV: Failure - Pinging Not Restarted\n"); 00340 SetMOOSVar("UPDATE_CMD", sCmdUpdateStatus, dfTimeNow); 00341 } 00342 00343 //show the outcome to the DB 00344 PublishFreshMOOSVariables(); 00345 00346 return true; 00347 } 00348 00352 void CADVInstrument::StartPinging() 00353 { 00354 00355 SendTermPair keepPinging("Start\r", m_sPrompt); 00356 m_Port.Write((char *)keepPinging.sSend.c_str(),keepPinging.sSend.size()); 00357 00358 return; 00359 } 00360 00365 bool CADVInstrument::SendADVUpdatedCommands(string &sCmdUpdateStatus, string sNewCmdString) 00366 { 00367 string sMOOSChompResult = MOOSChomp(sNewCmdString, ","); 00368 double dfWhen; 00369 string sWhatReply; 00370 bool bSuccess = true; 00371 00372 while(!sMOOSChompResult.empty()) 00373 { 00374 //take action here and talk to the ADV 00375 //have to add a <CR> to the command 00376 string sADVUpdateFormattedCmd = sMOOSChompResult + "\r"; 00377 00378 //we are writing and then reading too quickly for this device 00379 //MOOSPause(500); 00380 00381 m_Port.Write((char *)sADVUpdateFormattedCmd.c_str(),sADVUpdateFormattedCmd.size()); 00382 00383 while(!m_Port.GetLatest(sWhatReply,dfWhen)) 00384 { 00385 MOOSPause(10); 00386 } 00387 00388 if(GoodReply(sWhatReply)) 00389 { 00390 MOOSTrace("Update ADV: Succesful Update - %s\n", sADVUpdateFormattedCmd.c_str()); 00391 00392 //keep track of the success 00393 sCmdUpdateStatus += sMOOSChompResult + ": OK; "; 00394 } 00395 else 00396 { 00397 MOOSTrace("Update ADV: Failure - %s\n", sADVUpdateFormattedCmd.c_str()); 00398 00399 //keep track of the failure 00400 sCmdUpdateStatus += sMOOSChompResult + ": FAIL; "; 00401 00402 if(bSuccess) 00403 bSuccess = !bSuccess; 00404 } 00405 00406 sMOOSChompResult = MOOSChomp(sNewCmdString, ","); 00407 00408 } 00409 00410 return bSuccess; 00411 } 00412 00420 bool CADVInstrument::NewCommandsAreSkewed(CMOOSMsg & Msg, double dfTimeNow, string sNewCmdString) 00421 { 00422 double dfSkewTime; 00423 string sCmdUpdateStatus; 00424 00425 if((sNewCmdString.size() == 0) || 00426 Msg.IsSkewed(dfTimeNow, &dfSkewTime)) 00427 { 00428 00429 if((sNewCmdString.size() == 0)) 00430 { 00431 sCmdUpdateStatus = "Update ADV: Cmd SIZE = 0 - Aborted Update\n"; 00432 MOOSTrace("%s", sCmdUpdateStatus.c_str()); 00433 SetMOOSVar("UPDATE_CMD",sCmdUpdateStatus,MOOSTime()); 00434 } 00435 else 00436 { 00437 sCmdUpdateStatus = "Update ADV: Cmd [" + sNewCmdString + "] SKEWED - Aborted Update\n"; 00438 MOOSTrace("%s\n SkewTime: %f\n", sCmdUpdateStatus.c_str(), dfSkewTime); 00439 SetMOOSVar("UPDATE_CMD",sCmdUpdateStatus,MOOSTime()); 00440 } 00441 00442 return true; 00443 00444 } 00445 else if(dfSkewTime > FRESH_UPDATE) 00446 { 00447 sCmdUpdateStatus = "Update ADV: Cmd [" + sNewCmdString + "] STALE - Aborted Update\n"; 00448 MOOSTrace("%s\n SkewTime: %f\n", sCmdUpdateStatus.c_str(), dfSkewTime); 00449 SetMOOSVar("UPDATE_CMD",sCmdUpdateStatus,MOOSTime()); 00450 00451 return true; 00452 } 00453 else 00454 { 00455 MOOSTrace("Update ADV: Time Stamp - %f\n", Msg.m_dfTime); 00456 MOOSTrace("Update ADV: MOOS Time Stamp - %f\n", dfTimeNow); 00457 00458 return false; 00459 } 00460 00461 } 00462 00466 bool CADVInstrument::GetADVAttention() 00467 { 00468 string sWhatReply; 00469 double dfWhen; 00470 int nTries = 0; 00471 00472 //change the Termination Character we are looking for 00473 //and stop the ADV from talking 00474 m_Port.SetTermCharacter(m_sPrompt.c_str()[0]); 00475 m_Port.Break(); 00476 00477 //check reply... 00478 while(nTries++ < MAXTRIES) 00479 { 00480 //wait a second to let it stop streaming 00481 MOOSPause(1000); 00482 00483 while(!m_Port.GetLatest(sWhatReply,dfWhen)) 00484 { 00485 MOOSPause(10); 00486 } 00487 00488 if(GoodReply(sWhatReply)) 00489 { 00490 return true; 00491 } 00492 else 00493 { 00494 MOOSTrace("Update ADV: No Prompt Found - Retrying Break\n"); 00495 m_Port.Break(); 00496 } 00497 } 00498 00499 MOOSTrace("Update ADV: Check Cable Connection - Aborted Retry\n"); 00500 00501 return false; 00502 00503 } 00504 00512 bool CADVInstrument::ParseADVReply(string &sReply) 00513 { 00514 ADVINFO_LIST InfoList; 00515 string sCopy = sReply; 00516 double dfTimeNow = MOOSTime(); 00517 00518 string sWhat = MOOSChomp(sCopy," "); 00519 if(sWhat.length() > 0) 00520 { 00521 //This was a response we are not expecting 00522 MOOSTrace("Unknown ADV reply %s\n",sWhat.c_str()); 00523 return false; 00524 } 00525 else 00526 { 00527 while(!sCopy.empty()) 00528 { 00529 //step through the white space 00530 while((sWhat = MOOSChomp(sCopy," ")) == "") 00531 ; 00532 InfoList.push_back(sWhat); 00533 } 00534 } 00535 00536 ADVINFO_LIST::iterator p; 00537 if(p == InfoList.end() || InfoList.size() < 10){ 00538 MOOSTrace("Unknown ADV reply %s\n",sWhat.c_str()); 00539 return false; 00540 } 00541 else 00542 { 00543 p = InfoList.begin(); 00544 00545 //the first col is the sample no 00546 int nSamp = (int)atof((*p++).c_str()); 00547 int nXVel = (int)atof((*p++).c_str()); 00548 int nYVel = (int)atof((*p++).c_str()); 00549 int nZVel = (int)atof((*p++).c_str()); 00550 int nAmp1 = (int)atof((*p++).c_str()); 00551 int nAmp2 = (int)atof((*p++).c_str()); 00552 int nAmp3 = (int)atof((*p++).c_str()); 00553 int nCor1 = (int)atof((*p++).c_str()); 00554 int nCor2 = (int)atof((*p++).c_str()); 00555 int nCor3 = (int)atof((*p++).c_str()); 00556 00557 00558 //SetMOOSVar here 00559 //Convert to m/s 00560 SetMOOSVar("VEL_SAMPLE_NO", nSamp, dfTimeNow); 00561 SetMOOSVar("VEL_X",nXVel*.001,dfTimeNow); 00562 SetMOOSVar("VEL_Y",nYVel*.001,dfTimeNow); 00563 SetMOOSVar("VEL_Z",nZVel*.001,dfTimeNow); 00564 SetMOOSVar("AMP_1",nAmp1,dfTimeNow); 00565 SetMOOSVar("AMP_2",nAmp2,dfTimeNow); 00566 SetMOOSVar("AMP_3",nAmp3,dfTimeNow); 00567 SetMOOSVar("COR_1",nCor1,dfTimeNow); 00568 SetMOOSVar("COR_2",nCor2,dfTimeNow); 00569 SetMOOSVar("COR_3",nCor3,dfTimeNow); 00570 00571 } 00572 00573 //we are here so we processed the string 00574 if(PublishRaw()) 00575 { 00576 //yep user want to see raw data... 00577 m_Comms.Notify("ADV_RAW", sReply); 00578 } 00579 00580 return true; 00581 }