RosMsgSynchronizer.h
Go to the documentation of this file.
00001 #ifndef ROS_MSG_SYNCHRONIZER_H
00002 #define ROS_MSG_SYNCHRONIZER_H
00003 
00004 #include <math.h>
00005 #include <std_msgs/Header.h>
00006 
00012 template<class T1, class T2 = T1>
00013 class RosMsgSynchronizer
00014 {
00015 public:
00016     RosMsgSynchronizer()
00017         : windowDelta(0.0)
00018     {}
00019     ~RosMsgSynchronizer() {}
00020 
00021     inline void pushSource1(const T1& source1);
00022     inline void pushSource2(const T2& source2);
00023 
00024     void purgeBuffer();
00025     void purgeBuffer(const ros::Time& oldDataTime);
00026     unsigned int getBufferSize() const {return source1Buffer.size() + source2Buffer.size();}
00027 
00028     inline bool empty() const {return matches.empty();}
00029     inline unsigned int size() const {return matches.size();}
00030     inline const std::pair<T1, T2>& front() const
00031     {
00032         if (matches.empty()) throw std::out_of_range("front() called on empty RosMsgSynchronizer");
00033         return matches.begin()->second;
00034     }
00035     inline const std::pair<T1, T2>& back() const
00036     {
00037         if (matches.empty()) throw std::out_of_range("back() called on empty RosMsgSynchronizer");
00038         return (--matches.end())->second;
00039     }
00040     inline void pop()
00041     {
00042         if (!matches.empty()) matches.erase(matches.begin());
00043     }
00044     inline void clear() {matches.clear();}
00045 
00046     void setWindowDelta(double windowDelta_in)
00047     {
00048         if (windowDelta_in < 0.) throw std::out_of_range("windowDelta must greater than or equal to zero");
00049         windowDelta = windowDelta_in;
00050     }
00051 
00052 protected:
00053     std::map<ros::Time, T1> source1Buffer;
00054     std::map<ros::Time, T2> source2Buffer;
00055     std::map<ros::Time, std::pair<T1, T2> > matches;
00056 
00057     template <class T3, class T4>
00058     bool findMatch(std::map<ros::Time, T3>& sourceBuffer, const T4& find, T3& match);
00059 
00060     double windowDelta;
00061 };
00062 
00063 template <class T1, class T2>
00064 void RosMsgSynchronizer<T1, T2>::pushSource1(const T1& source1)
00065 {
00066     T2 match;
00067     if (findMatch(source2Buffer, source1, match))
00068     {
00069         matches[source1.header.stamp] = make_pair(source1, match);
00070         source2Buffer.erase(match.header.stamp);
00071     }
00072     else
00073     {
00074         source1Buffer[source1.header.stamp] = source1;
00075     }
00076 }
00077 
00078 template <class T1, class T2>
00079 void RosMsgSynchronizer<T1, T2>::pushSource2(const T2& source2)
00080 {
00081     T1 match;
00082     if (findMatch(source1Buffer, source2, match))
00083     {
00084         matches[match.header.stamp] = make_pair(match, source2);
00085         source1Buffer.erase(match.header.stamp);
00086     }
00087     else
00088     {
00089         source2Buffer[source2.header.stamp] = source2;
00090     }
00091 }
00092 
00093 template <class T1, class T2>
00094 void RosMsgSynchronizer<T1, T2>::purgeBuffer()
00095 {
00096     source1Buffer.clear();
00097     source2Buffer.clear();
00098 }
00099 
00100 template <class T1, class T2>
00101 void RosMsgSynchronizer<T1, T2>::purgeBuffer(const ros::Time& oldDataTime)
00102 {
00103     typename std::map<ros::Time, T1>::iterator source1It = source1Buffer.lower_bound(oldDataTime);
00104     source1Buffer.erase(source1Buffer.begin(), source1It);
00105 
00106     typename std::map<ros::Time, T2>::iterator source2It = source2Buffer.lower_bound(oldDataTime);
00107     source2Buffer.erase(source2Buffer.begin(), source2It);
00108 }
00109 
00110 template <class T1, class T2>
00111 template <class T3, class T4>
00112 bool RosMsgSynchronizer<T1, T2>::findMatch(std::map<ros::Time, T3>& sourceBuffer, const T4& find, T3& match)
00113 {
00114     // look for closest match in sourceBuffer
00115     if (sourceBuffer.empty())
00116     {
00117         return false;
00118     }
00119 
00120     double dT1 = windowDelta + 1.;
00121     double dT2 = dT1;
00122 
00123     // get closest one that is greater
00124     typename std::map<ros::Time, T3>::iterator sourceIt = sourceBuffer.upper_bound(find.header.stamp);
00125     // if it exists and is less than the delta, we have a match
00126     if (sourceIt != sourceBuffer.end() && (dT1 = (sourceIt->first - find.header.stamp).toSec()) <= windowDelta)
00127     {
00128         match = sourceIt->second;
00129     }
00130 
00131     // check the closest one less than to find the closest one
00132     if (sourceIt != sourceBuffer.begin())
00133     {
00134         --sourceIt;
00135         if ((dT2 = (find.header.stamp - sourceIt->first).toSec()) <= windowDelta && dT2 < dT1)
00136         {
00137             dT1 = dT2;
00138             match = sourceIt->second;
00139         }
00140     }
00141 
00142     if (dT1 <= windowDelta)
00143     {
00144         return true;
00145     }
00146 
00147     return false;
00148 }
00149 
00150 #endif


robodyn_utilities
Author(s):
autogenerated on Thu Jun 6 2019 18:56:07