MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/Instruments/Ocean/iADV/ADVInstrument.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 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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines