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
00115 if (sourceBuffer.empty())
00116 {
00117 return false;
00118 }
00119
00120 double dT1 = windowDelta + 1.;
00121 double dT2 = dT1;
00122
00123
00124 typename std::map<ros::Time, T3>::iterator sourceIt = sourceBuffer.upper_bound(find.header.stamp);
00125
00126 if (sourceIt != sourceBuffer.end() && (dT1 = (sourceIt->first - find.header.stamp).toSec()) <= windowDelta)
00127 {
00128 match = sourceIt->second;
00129 }
00130
00131
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