MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/NavigationAndControl/MOOSNavLib/MOOSSensorChannel.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 Basic (Common) Application. 
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 // MOOSSensorChannel.cpp: implementation of the CMOOSSensorChannel class.
00032 //
00034 #ifdef _WIN32
00035 #pragma warning(disable : 4786)
00036 #endif
00037 
00038 #include "MOOSSensorChannel.h"
00039 #include "math.h"
00040 
00042 // Construction/Destruction
00044 
00045 CMOOSSensorChannel::CMOOSSensorChannel()
00046 {
00047     //how deep should the history be
00048     m_nHistoryDepth = 4;
00049     
00050 
00051     //by defualt streams are active at birth
00052     m_bActive = true;
00053 
00054     //this must be set for each stream in the mission file
00055     //if it is to have an effect
00056     m_dfNoiseLimit = 10;
00057 
00058     m_dfMean = 0;
00059 
00060     m_dfStd = 0;
00061 
00062     m_dfHistoryTimeSpan = 20;
00063 
00064     m_bBuilt = false;
00065 
00066 }
00067 
00068 CMOOSSensorChannel::~CMOOSSensorChannel()
00069 {
00070 
00071 }
00072 
00073 
00074 bool CMOOSSensorChannel::SetHistoryDepth(int nDepth)
00075 {
00076     m_nHistoryDepth = nDepth;
00077     return true;
00078 }
00079 
00080 bool CMOOSSensorChannel::Add(CMOOSObservation &rObs)
00081 {
00082     
00083     //have we already stored this observation?
00084     OBSLIST::iterator w;
00085     for(w = m_History.begin();w!=m_History.end();w++)
00086     {
00087         if(w->m_nID==rObs.m_nID)
00088         {
00089             //yes!
00090             //we do nothing (this isn't an error)
00091             return true;
00092         }
00093     }
00094     
00095     //no -> store it now
00096     m_History.push_front(rObs);
00097     
00098     //now sort list with biggest time at the front
00099     //default behaviour of sort is in ascending order..
00100     m_History.sort(greater< CMOOSObservation >());
00101     
00102     
00103     if(m_History.size()==m_nHistoryDepth)
00104     {
00105         AddToOutput("Working history (%d deep) for %s : BUILT",
00106             m_nHistoryDepth,
00107             m_sName.c_str());
00108         m_bBuilt = true;
00109     }
00110     
00111     
00112     //now keep history a sensible length
00113     double dfSpan = m_History.front().m_dfTime-m_History.back().m_dfTime;
00114     while(m_History.size() >m_nHistoryDepth || dfSpan > m_dfHistoryTimeSpan)
00115     {        
00116         m_History.pop_back();
00117         dfSpan = m_History.front().m_dfTime-m_History.back().m_dfTime;
00118     }
00119     
00120     return true;
00121 }
00122 
00123 bool CMOOSSensorChannel::Agrees(CMOOSObservation &rObs)
00124 {
00125     //if small history can't make a call
00126     if(m_History.size()<m_nHistoryDepth)
00127     {
00128         return false;
00129     }
00130     
00131     //set up the median filter
00132     m_MedianFilter.Initialise(0.9,0.8);
00133 
00134 
00135     bool bTest = false;
00136     if(bTest)
00137     {
00138         //test data 
00139         double dfTest[] = {7,2,4,4,5,6,7};
00140 
00141         int i = 0;
00142         for(i =0;i<sizeof(dfTest)/sizeof(double);i++)
00143         {
00144             m_MedianFilter.AddData(i,dfTest[i],i);
00145         }
00146 
00147         //calculte outliers
00148         m_MedianFilter.Calculate();
00149 
00150         //figure out how well the channel is doing (is it clean data)
00151         AutoDiagnose();
00152 
00153         for(i =0;i<sizeof(dfTest)/sizeof(double);i++)
00154         {
00155             if(!m_MedianFilter.IsInlier(i))
00156             {
00157                 MOOSTrace("Rejected fake obs %d\n",i);
00158             }
00159         }
00160         return true;        
00161     }
00162     else
00163     {
00164         //add data
00165         OBSLIST::iterator p;
00166 
00167         for(p = m_History.begin();p!=m_History.end();p++)
00168         {
00169             m_MedianFilter.AddData(p->m_dfTime,p->m_dfData,p->m_nID);
00170         }
00171 
00172     
00173         //calculte outliers
00174         m_MedianFilter.Calculate();
00175 
00176         //figure out how well the channel is doing (is it clean data)
00177         AutoDiagnose();
00178 
00179         if(m_bActive)
00180         {
00181             //previous auto-diagnose could have caused us to turn off..
00182             return   m_MedianFilter.IsInlier(rObs.m_nID);
00183         }
00184         else
00185         {
00186             //it did...
00187             return false;
00188         }
00189     }
00190 }
00191 
00192 
00193 bool CMOOSSensorChannel::SetNoiseLimit(double dfLimit)
00194 {
00195     m_dfNoiseLimit = dfLimit;
00196     return true;
00197 }
00198 
00199 bool CMOOSSensorChannel::AutoDiagnose()
00200 {
00201 
00202 
00203    //figure out trajectory statistics...
00204     if(m_History.size()<m_nHistoryDepth)
00205         return true;
00206 
00207     //need to fit a least medians line to data....
00208     double dfChannelNoise;
00209     double dfOutlierRatio;
00210     double dfTotalStd;
00211     double dfMedianDistance;
00212     m_MedianFilter.GetStatus(    dfChannelNoise,
00213                                 dfOutlierRatio,
00214                                 dfTotalStd,
00215                                 dfMedianDistance);
00216 
00217     //MOOSTrace("Channel Noise = %f, OutlierRatio = %f%%\n",dfChannelNoise,dfOutlierRatio);
00218 
00219     //robust stats is only good to about 50 % in ideal circumstances we'll back off a little
00220 //    if((dfOutlierRatio>50 ||dfChannelNoise>=m_dfNoiseLimit) && dfTotalStd>m_dfNoiseLimit )
00221     if((dfOutlierRatio>50 ||dfMedianDistance>=m_dfNoiseLimit))
00222     {
00223         if(m_bActive==true)
00224         {
00225             
00226             OBSLIST::iterator w;
00227             for(w = m_History.begin();w!=m_History.end();w++)
00228             {
00229                 MOOSTrace("Data = %f\n",w->m_dfData);
00230             }
00231 
00232             
00233             string sOutput = MOOSFormat("%s is suspect %.1f percent are outliers (of %d), MedianDev = %.4f (limit %.4f): turning stream off!\n",
00234                 m_sName.c_str(),
00235                 dfOutlierRatio,
00236                 m_nHistoryDepth,
00237                 dfMedianDistance,
00238                 m_dfNoiseLimit);
00239 
00240             AddToOutput(sOutput);
00241         }
00242 
00243         m_bActive=false;
00244     }
00245     else
00246     {
00247         if(m_bActive==false)
00248         {
00249             //tell the world we are re-enabling stream...
00250             string sOutput = MOOSFormat("Sensor Channel %s better behaved now : turning stream on!\n",
00251                 m_sName.c_str());
00252 
00253             AddToOutput(sOutput);
00254         }
00255         m_bActive = true;
00256     }
00257 
00258     return true;
00259 }
00260 
00261 bool CMOOSSensorChannel::IsOnline()
00262 {
00263     return m_History.size()>=m_nHistoryDepth;
00264 }
00265 
00266 double CMOOSSensorChannel::GetPercentFull()
00267 {
00268     return 100.0*m_History.size()/m_nHistoryDepth;
00269 }
00270 
00271 void CMOOSSensorChannel::Trace()
00272 {
00273     MOOSTrace("\n*** CMOOSSensorChannel::Trace() ***\n");
00274     m_MedianFilter.Trace();
00275 }
00276 
00277 bool CMOOSSensorChannel::IsBuilt()
00278 {
00279     return m_bBuilt;
00280 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines