MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/Core/MOOSLIB/MOOSMsg.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 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 Core 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 // MOOSMsg.cpp: implementation of the CMOOSMsg class.
00031 //
00033 #ifdef _WIN32
00034 #pragma warning(disable : 4786)
00035 #endif
00036 
00037 #include <MOOSGenLib/MOOSGenLib.h>
00038 #include "MOOSMsg.h"
00039 #include "MOOSException.h"
00040 #include "MOOSGlobalHelper.h"
00041 #include <iostream>
00042 #include <sstream>
00043 #include <iomanip>
00044 #include <cmath>
00045 #include <cstring>
00046 
00047 using namespace std;
00048 
00050 // Construction/Destruction
00052 
00053 
00054 CMOOSMsg::CMOOSMsg()
00055 {
00056     m_cMsgType=MOOS_NULL_MSG;
00057     m_cDataType=MOOS_DOUBLE;
00058     m_dfTime = -1;
00059     m_dfVal = -1;
00060     m_dfVal2 = -1;
00061     m_nID = -1;
00062         m_sSrc = "";
00063         m_sSrcAux = "";
00064 }
00065 
00066 CMOOSMsg::~CMOOSMsg()
00067 {
00068 
00069 }
00070 
00071 CMOOSMsg::CMOOSMsg(char cMsgType,const std::string  & sKey,double dfVal,double dfTime)
00072 {
00073     m_cMsgType = cMsgType;
00074     m_dfVal = dfVal;
00075     m_dfVal2 = -1;
00076     m_cDataType = MOOS_DOUBLE;
00077     m_sKey = sKey;
00078     m_dfTime = -1;
00079     m_nID = -1;
00080 
00081     if(dfTime==-1)
00082     {
00083         m_dfTime = MOOSTime();
00084     }
00085     else
00086     {
00087         m_dfTime=dfTime;
00088     }
00089 }
00090 
00091 
00092 CMOOSMsg::CMOOSMsg(char cMsgType,const std::string & sKey,const std::string &sVal,double dfTime)
00093 {
00094     m_cMsgType = cMsgType;
00095     m_dfVal = -1;
00096     m_dfVal2 = -1;
00097     m_cDataType = MOOS_STRING;
00098     m_sKey = sKey;
00099     m_sVal = sVal;
00100     m_dfTime = -1;
00101     m_nID = -1;
00102 
00103     if(dfTime==-1)
00104     {
00105         m_dfTime = MOOSTime();
00106     }
00107     else
00108     {
00109         m_dfTime=dfTime;
00110     }
00111 }
00112 
00113 
00114 void CMOOSMsg::MarkAsBinary()
00115 {
00116         m_cDataType=MOOS_BINARY_STRING;
00117 }
00118 
00120 template<class T> void CopyToBufferAsLittleEndian(T Var,unsigned char* pBuffer)
00121 {
00122     int nSize = sizeof(T);
00123     if(!IsLittleEndian())
00124     {
00125         //watch out we need to switch to MOOS standard of sending data
00126         //as little endian (natural for x86 architectures)
00127         T ACopy = SwapByteOrder<T>(Var);
00128 
00129         memcpy((void*)(pBuffer),(void*)(&ACopy),nSize);
00130     }
00131     else
00132     {
00133         //x86 machines should execute this...
00134         memcpy((void*)(pBuffer),(void*)(&Var),nSize);
00135     }
00136 }
00137 
00138 
00139 template<class T> T CopyFromBufferAsLittleEndian(unsigned char* pBuffer)
00140 {
00141     int nSize = sizeof(T);
00142     T Val;
00143     memcpy((void*)(&Val),(void*)(pBuffer),nSize);
00144     if(!IsLittleEndian())
00145     {
00146         //watch out we need to switch to MOOS standard of sending data
00147         //as little endian (natural for x86 architectures)
00148         Val = SwapByteOrder<T>(Val);
00149 
00150     }    
00151 
00152     return Val;
00153 }
00154 
00155 
00156 void  CMOOSMsg::operator << (double & dfVal)
00157 {
00158     int nSize = sizeof(dfVal);
00159 
00160     if(CanSerialiseN(nSize))
00161     {
00162         CopyToBufferAsLittleEndian<double>(dfVal,m_pSerializeBuffer);
00163         m_pSerializeBuffer+=nSize;
00164     }
00165     else
00166     {
00167         throw CMOOSException("CMOOSMsg::operator << Out Of Space");
00168     }
00169 }
00170 
00171 void  CMOOSMsg::operator >> (double & dfVal)
00172 {
00173         
00174     int nSize = sizeof(dfVal);
00175 
00176     if(CanSerialiseN(nSize))
00177     {
00178         dfVal = CopyFromBufferAsLittleEndian<double>(m_pSerializeBuffer);
00179         //memcpy((void*)(&dfVal),(void*)(m_pSerializeBuffer),nSize);
00180         m_pSerializeBuffer+=nSize;
00181     }
00182     else
00183     {
00184         throw CMOOSException("CMOOSMsg::operator >> Out Of Space");
00185     }
00186 }
00187 
00188 
00189 
00190 void  CMOOSMsg::operator << (string &   sVal)
00191 {
00192 /*
00193     int nSize = sVal.size()+1;
00194 
00195     if(CanSerialiseN(nSize))
00196     {
00197         strcpy((char *)m_pSerializeBuffer,sVal.c_str());
00198         m_pSerializeBuffer+=nSize;
00199     }
00200     else
00201     {
00202         throw CMOOSException("CMOOSMsg::operator << Out Of Space");
00203     }
00204  */
00205         int nSize = sVal.size();
00206         *this<<nSize;
00207         
00208         if(CanSerialiseN(nSize))
00209     {
00210         memcpy((char *)m_pSerializeBuffer,sVal.data(),nSize);
00211         m_pSerializeBuffer+=nSize;
00212     }
00213     else
00214     {
00215         throw CMOOSException("CMOOSMsg::operator << Out Of Space");
00216     }
00217         
00218 }
00219 
00220 void  CMOOSMsg::operator >> (string & sVal)
00221 {/*
00222     int nSize = strlen((char*)m_pSerializeBuffer)+1;
00223 
00224     if(CanSerialiseN(nSize))
00225     {
00226         sVal.insert(0,(char*)m_pSerializeBuffer,nSize-1);
00227         m_pSerializeBuffer+=nSize;
00228     }
00229     else
00230     {
00231         throw CMOOSException("CMOOSMsg::operator >> Out Of Space");
00232     }
00233   */
00234         int nSize;
00235         *this>>nSize;
00236         
00237     if(CanSerialiseN(nSize))
00238     {
00239         sVal.insert(0,(char*)m_pSerializeBuffer,nSize);
00240         m_pSerializeBuffer+=nSize;
00241     }
00242     else
00243     {
00244         throw CMOOSException("CMOOSMsg::operator >> Out Of Space");
00245     }
00246         
00247 }
00248 
00249 
00250 void  CMOOSMsg::operator << (int & nVal)
00251 {
00252     int nSize = sizeof(int);
00253 
00254     if(CanSerialiseN(nSize))
00255     {
00256         CopyToBufferAsLittleEndian<int>(nVal,m_pSerializeBuffer);
00257         //        memcpy((void*)(m_pSerializeBuffer),(void*)(&nVal),sizeof(nVal));
00258         m_pSerializeBuffer+=nSize;
00259     }
00260     else
00261     {
00262         throw CMOOSException("CMOOSMsg::operator << Out Of Space");
00263     }
00264 
00265 }
00266 void  CMOOSMsg::operator >> (int & nVal)
00267 {
00268     int nSize = sizeof(int);
00269 
00270     if(CanSerialiseN(nSize))
00271     {
00272         nVal = CopyFromBufferAsLittleEndian<int>(m_pSerializeBuffer);
00273 
00274         //memcpy((void*)(&nVal),(void*)(m_pSerializeBuffer),sizeof(nVal));
00275         m_pSerializeBuffer+=nSize;
00276     }
00277     else
00278     {
00279         throw CMOOSException("CMOOSMsg::operator >> Out Of Space");
00280     }
00281 
00282 }
00283 
00284 void  CMOOSMsg::operator << (char &  cVal)
00285 {
00286     int nSize = sizeof(cVal);
00287 
00288     if(CanSerialiseN(nSize))
00289     {
00290         memcpy((void*)(m_pSerializeBuffer),(void*)(&cVal),sizeof(cVal));
00291         m_pSerializeBuffer+=sizeof(cVal);
00292     }
00293     else
00294     {
00295         throw CMOOSException("CMOOSMsg::operator << Out Of Space");
00296     }
00297 
00298 }
00299 
00300 void  CMOOSMsg::operator >> (char & cVal)
00301 {
00302     int nSize = sizeof(cVal);
00303 
00304     if(CanSerialiseN(nSize))
00305     {
00306         memcpy((void*)(&cVal),(void*)m_pSerializeBuffer,sizeof(cVal));
00307         m_pSerializeBuffer+=sizeof(cVal);
00308     }
00309     else
00310     {
00311         throw CMOOSException("CMOOSMsg::operator >> Out Of Space");
00312     }
00313 
00314 }
00315 
00316 unsigned int CMOOSMsg::GetSizeInBytesWhenSerialised() const
00317 {
00318     unsigned int nInt = 2*sizeof(int);
00319     unsigned int nChar = 2*sizeof(char);
00320     unsigned int nString = sizeof(int)+m_sSrc.size()+
00321 #ifndef DISABLE_AUX_SOURCE
00322             sizeof(int)+m_sSrcAux.size()+
00323 #endif
00324             sizeof(int)+m_sOriginatingCommunity.size()+
00325             sizeof(int)+m_sKey.size()+
00326             sizeof(int)+m_sVal.size();
00327 
00328     unsigned int nDouble = 3*sizeof(double);
00329 
00330     return nInt+nChar+nString+nDouble;
00331 
00332 }
00333 
00334 
00335 int CMOOSMsg::Serialize(unsigned char *pBuffer, int nLen, bool bToStream)
00336 {
00337 
00338     if(bToStream)
00339     {
00340         try
00341         {
00342 
00343             //MOOSTrace("Packing Msg with community %s\n",m_sOriginatingCommunity.c_str());
00344 
00345             m_pSerializeBuffer = pBuffer;
00346             m_pSerializeBufferStart = pBuffer;
00347             m_nSerializeBufferLen = nLen;
00348 
00349             //leave space for total byte count
00350             m_pSerializeBuffer +=sizeof(int);
00351 
00352             //what is message ID;
00353             (*this)<<m_nID;
00354 
00355             //what type of message is this?
00356             (*this)<<m_cMsgType;
00357 
00358             //what type of data is this?
00359             (*this)<<m_cDataType;
00360 
00361             //from whence does it come
00362             (*this)<<m_sSrc;
00363                         
00364 #ifndef DISABLE_AUX_SOURCE
00365                         //extra source info
00366                         (*this)<<m_sSrcAux;
00367 #endif
00368 
00369             //and from which community?
00370             (*this)<<m_sOriginatingCommunity;
00371 
00372             //what
00373             (*this)<<m_sKey;
00374 
00375             //what time was the notification?
00376             (*this)<<m_dfTime;
00377 
00378             //double data
00379             (*this)<<m_dfVal;
00380 
00381             //double data
00382             (*this)<<m_dfVal2;
00383 
00384             //string data
00385             (*this)<<m_sVal;
00386 
00387 
00388             //how many bytes in total have we written (this includes an int at the start)?
00389             m_nLength = m_pSerializeBuffer-m_pSerializeBufferStart;
00390 
00391             //reset destination
00392             m_pSerializeBuffer = m_pSerializeBufferStart;
00393 
00394             //write the number of bytes
00395             (*this)<<m_nLength;
00396 
00397 
00398 
00399 
00400         }
00401         catch(CMOOSException e)
00402         {
00403             MOOSTrace("exception : CMOOSMsg::Serialize failed: %s\n ",e.m_sReason);
00404                         MOOSTrace("perhaps accummulated messages exceeded available buffer space of %d bytes\n", m_nSerializeBufferLen);
00405             return -1;
00406         }
00407     }
00408     else
00409     {
00410         //this is extracting from a stream....
00411 
00412         try
00413         {
00414             m_pSerializeBuffer = pBuffer;
00415             m_pSerializeBufferStart = pBuffer;
00416             m_nSerializeBufferLen = nLen;
00417 
00418 
00419             (*this)>>m_nLength;
00420 
00421             //what is message ID;
00422             (*this)>>m_nID;
00423 
00424             //what type of message is this?
00425             (*this)>>m_cMsgType;
00426 
00427             //what type of data is this?
00428             (*this)>>m_cDataType;
00429 
00430             //from whence does it come
00431             (*this)>>m_sSrc;
00432 
00433 #ifndef DISABLE_AUX_SOURCE
00434                         //extra source info
00435                         (*this)>>m_sSrcAux;
00436 #endif                  
00437             //and from which community?
00438             (*this)>>m_sOriginatingCommunity;
00439 
00440             //what
00441             (*this)>>m_sKey;
00442 
00443             //what time was the notification?
00444             (*this)>>m_dfTime;
00445 
00446             //double data
00447             (*this)>>m_dfVal;
00448 
00449             //double data
00450             (*this)>>m_dfVal2;
00451 
00452 
00453             //string data
00454             (*this)>>m_sVal;
00455 
00456         }
00457         catch(CMOOSException e)
00458         {
00459             MOOSTrace("exception : CMOOSMsg::Serialize failed: %s\n ",e.m_sReason);
00460 
00461             return -1;
00462         }
00463 
00464     }
00465     return m_nLength;
00466 
00467 }
00468 
00469 int CMOOSMsg::GetLength()
00470 {
00471     return m_nLength;
00472 }
00473 
00474 bool CMOOSMsg::CanSerialiseN(int N)
00475 {
00476     return      (m_pSerializeBuffer-m_pSerializeBufferStart)+N<=m_nSerializeBufferLen;
00477 }
00478 
00479 bool CMOOSMsg::IsType(char cType) const
00480 {
00481     return m_cMsgType==cType;
00482 }
00483 
00484 void CMOOSMsg::Trace()
00485 {
00486     MOOSTrace("Type=%c DataType=%c Key =%s ",m_cMsgType,m_cDataType,m_sKey.c_str());
00487 
00488 
00489     switch(m_cDataType)
00490     {
00491     case MOOS_DOUBLE:
00492         MOOSTrace("Data=%f ",m_dfVal);
00493         break;
00494     case MOOS_STRING:
00495         MOOSTrace("Data=%s ",m_sVal.c_str());
00496         break;
00497         case MOOS_BINARY_STRING:
00498                         MOOSTrace("Data=%.3f KB of binary       data ",m_sVal.size()/1000.0);
00499                         break;
00500                         
00501     }
00502 
00503 
00504     MOOSTrace("Source= %s Time = %10.3f\n",m_sSrc.c_str(),m_dfTime);
00505 }
00506 
00507 bool CMOOSMsg::IsYoungerThan(double dfAge) const
00508 {
00509     return m_dfTime>=dfAge;
00510 }
00511 
00521 bool CMOOSMsg::IsSkewed(double dfTimeNow, double * pdfSkew)
00522 {
00523     //if we are in playback mode (a global app wide flag)
00524     //then skew may not mean anything.. (we can stop and start at will)
00525     if(IsMOOSPlayBack())
00526     {
00527         dfTimeNow  = m_dfTime;
00528     }
00529 
00530     double dfSkew = fabs(dfTimeNow - m_dfTime);
00531 
00532     if(pdfSkew != NULL)
00533     {
00534         *pdfSkew = dfSkew;
00535     }
00536 
00537     return (dfSkew > SKEW_TOLERANCE) ? true : false;
00538 
00539 }
00540 
00541 
00542 
00543 
00544 
00545 
00546 string CMOOSMsg::GetAsString(int nFieldWidth/*=12*/, int nNumDP/*=5*/)
00547 {
00548     ostringstream os;
00549 
00550     os.setf(ios::left);
00551 
00552     if(GetTime()!=-1)
00553     {        
00554         if(IsDataType(MOOS_DOUBLE))
00555         {
00556                         os.setf(ios::fixed);
00557 
00558             os<<setw(nFieldWidth)<<setprecision(nNumDP)<<m_dfVal<<ends;       
00559         }
00560                 else if(IsDataType(MOOS_BINARY_STRING))
00561                 {
00562                         os<<"BINARY DATA ["<<m_sVal.size()/1000.0<<" kB]"<<ends;
00563                 }
00564         else 
00565         {
00566             os<<m_sVal.c_str()<<ends;
00567         }
00568     }
00569     else
00570     {
00571         os<<setw(nFieldWidth)<<"NotSet"<<ends;       
00572     }
00573 
00574     return os.str();
00575 }
00576 
00577 bool CMOOSMsg::IsDataType(char cDataType) const
00578 {
00579     return m_cDataType == cDataType;
00580 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines