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 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 }