00001 // ***************************************************************************** 00002 // 00003 // Copyright (c) 2015, Southwest Research Institute® (SwRI®) 00004 // All rights reserved. 00005 // 00006 // Redistribution and use in source and binary forms, with or without 00007 // modification, are permitted provided that the following conditions are met: 00008 // * Redistributions of source code must retain the above copyright 00009 // notice, this list of conditions and the following disclaimer. 00010 // * Redistributions in binary form must reproduce the above copyright 00011 // notice, this list of conditions and the following disclaimer in the 00012 // documentation and/or other materials provided with the distribution. 00013 // * Neither the name of Southwest Research Institute® (SwRI®) nor the 00014 // names of its contributors may be used to endorse or promote products 00015 // derived from this software without specific prior written permission. 00016 // 00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 // ARE DISCLAIMED. IN NO EVENT SHALL SOUTHWEST RESEARCH INSTITUTE BE LIABLE FOR ANY 00021 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00022 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00023 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00024 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00026 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00027 // 00028 // ***************************************************************************** 00029 #ifndef SWRI_ROSCPP_H_ 00030 #define SWRI_ROSCPP_H_ 00031 00032 namespace swri 00033 { 00034 class Timer; 00035 class TimerImpl 00036 { 00037 protected: 00038 ros::Timer timer_; 00039 ros::Duration desired_period_; 00040 00041 int ticks_; 00042 00043 ros::WallTime tick_begin_wall_; 00044 ros::Time tick_begin_normal_; 00045 00046 ros::Duration total_periods_; 00047 ros::Duration min_period_; 00048 ros::Duration max_period_; 00049 00050 ros::WallDuration total_durations_; 00051 ros::WallDuration min_duration_; 00052 ros::WallDuration max_duration_; 00053 00054 void tickBegin() 00055 { 00056 tick_begin_wall_ = ros::WallTime::now(); 00057 00058 ros::Time now = ros::Time::now(); 00059 if (ticks_ > 0) { 00060 ros::Duration period = now - tick_begin_normal_; 00061 total_periods_ += period; 00062 00063 if (ticks_ == 1) { 00064 min_period_ = period; 00065 max_period_ = period; 00066 } else { 00067 min_period_ = std::min(min_period_, period); 00068 max_period_ = std::max(max_period_, period); 00069 } 00070 } 00071 tick_begin_normal_ = now; 00072 } 00073 00074 void tickEnd() 00075 { 00076 ros::WallTime end_time_ = ros::WallTime::now(); 00077 ros::WallDuration duration = end_time_ - tick_begin_wall_; 00078 total_durations_ += duration; 00079 if (ticks_ == 0) { 00080 min_duration_ = duration; 00081 max_duration_ = duration; 00082 } else { 00083 min_duration_ = std::min(min_duration_, duration); 00084 max_duration_ = std::max(max_duration_, duration); 00085 } 00086 ticks_++; 00087 } 00088 00089 public: 00090 TimerImpl() 00091 { 00092 resetStatistics(); 00093 } 00094 00095 ros::Duration desiredPeriod() const 00096 { 00097 return desired_period_; 00098 } 00099 00100 void resetStatistics() 00101 { 00102 ticks_ = 0; 00103 } 00104 00105 // The number of times the timer callback has been called. 00106 size_t ticks() const 00107 { 00108 return ticks_; 00109 } 00110 00111 double meanFrequencyHz() const 00112 { 00113 if (ticks_ < 2) { 00114 return 0.0; 00115 } else { 00116 return 1e9 / meanPeriod().toNSec(); 00117 } 00118 } 00119 00120 ros::Duration meanPeriod() const 00121 { 00122 if (ticks_ < 2) { 00123 return ros::DURATION_MAX; 00124 } else { 00125 return ros::Duration(total_periods_.toSec() / (ticks_ - 1)); 00126 } 00127 } 00128 00129 ros::Duration minPeriod() const 00130 { 00131 if (ticks_ < 2) { 00132 return ros::DURATION_MAX; 00133 } else { 00134 return min_period_; 00135 } 00136 } 00137 00138 ros::Duration maxPeriod() const 00139 { 00140 if (ticks_ < 2) { 00141 return ros::DURATION_MAX; 00142 } else { 00143 return max_period_; 00144 } 00145 } 00146 00147 ros::WallDuration meanDuration() const 00148 { 00149 if (ticks_ == 0) { 00150 return ros::WallDuration(0.0); 00151 } else { 00152 return ros::WallDuration(total_durations_.toSec() / ticks_); 00153 } 00154 } 00155 00156 ros::WallDuration minDuration() const 00157 { 00158 if (ticks_ == 0) { 00159 return ros::WallDuration(0.0); 00160 } else { 00161 return min_duration_; 00162 } 00163 } 00164 00165 ros::WallDuration maxDuration() const 00166 { 00167 if (ticks_ == 0) { 00168 return ros::WallDuration(0.0); 00169 } else { 00170 return max_duration_; 00171 } 00172 } 00173 }; // class TimerImpl 00174 00175 template<class T> 00176 class TypedTimerImpl : public TimerImpl 00177 { 00178 T *obj_; 00179 void (T::*callback_)(const ros::TimerEvent &); 00180 00181 public: 00182 TypedTimerImpl( 00183 ros::NodeHandle &nh, 00184 ros::Duration period, 00185 void(T::*callback)(const ros::TimerEvent&), 00186 T *obj) 00187 { 00188 callback_ = callback; 00189 obj_ = obj; 00190 00191 desired_period_ = period; 00192 timer_ = nh.createTimer(period, 00193 &TypedTimerImpl::handleTimer, 00194 this); 00195 } 00196 00197 void handleTimer(const ros::TimerEvent &event) 00198 { 00199 tickBegin(); 00200 (obj_->*callback_)(event); 00201 tickEnd(); 00202 } 00203 }; // class TypedTimerImpl 00204 } // namespace swri 00205 #endif // SWRI_ROSCPP_H_