Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00037 #ifndef GENERIC_ANALYZER_BASE_H
00038 #define GENERIC_ANALYZER_BASE_H
00039
00040 #include <map>
00041 #include <ros/ros.h>
00042 #include <vector>
00043 #include <string>
00044 #include <sstream>
00045 #include <boost/shared_ptr.hpp>
00046 #include <boost/regex.hpp>
00047 #include <pluginlib/class_list_macros.hpp>
00048 #include "diagnostic_msgs/DiagnosticStatus.h"
00049 #include "diagnostic_msgs/KeyValue.h"
00050 #include "diagnostic_aggregator/analyzer.h"
00051 #include "diagnostic_aggregator/status_item.h"
00052
00053 namespace diagnostic_aggregator {
00054
00065 class GenericAnalyzerBase : public Analyzer
00066 {
00067 public:
00068 GenericAnalyzerBase() :
00069 nice_name_(""), path_(""), timeout_(-1.0), num_items_expected_(-1),
00070 discard_stale_(false), has_initialized_(false), has_warned_(false)
00071 { }
00072
00073 virtual ~GenericAnalyzerBase() { items_.clear(); }
00074
00075
00076
00077
00078 bool init(const std::string path, const ros::NodeHandle &n) = 0;
00079
00080
00081
00082
00083
00084
00085 bool init(const std::string path, const std::string nice_name,
00086 double timeout = -1.0, int num_items_expected = -1, bool discard_stale = false)
00087 {
00088 num_items_expected_ = num_items_expected;
00089 timeout_ = timeout;
00090 nice_name_ = nice_name;
00091 path_ = path;
00092 discard_stale_ = discard_stale;
00093 last_header_status_change_ = ros::Time::now();
00094 last_header_level_ = 0;
00095
00096 if (discard_stale_ && timeout <= 0)
00097 {
00098 ROS_WARN("Cannot discard stale items if no timeout specified. No items will be discarded");
00099 discard_stale_ = false;
00100 }
00101
00102 has_initialized_ = true;
00103
00104 return true;
00105 }
00106
00110 virtual bool analyze(const boost::shared_ptr<StatusItem> item)
00111 {
00112 if (!has_initialized_ && !has_warned_)
00113 {
00114 has_warned_ = true;
00115 ROS_ERROR("GenericAnalyzerBase is asked to analyze diagnostics without being initialized. init() must be called in order to correctly use this class.");
00116 }
00117
00118 if (!has_initialized_)
00119 return false;
00120
00121 items_[item->getName()] = item;
00122
00123 return has_initialized_;
00124 }
00125
00131 virtual std::vector<boost::shared_ptr<diagnostic_msgs::DiagnosticStatus> > report()
00132 {
00133 if (!has_initialized_ && !has_warned_)
00134 {
00135 has_warned_ = true;
00136 ROS_ERROR("GenericAnalyzerBase is asked to report diagnostics without being initialized. init() must be called in order to correctly use this class.");
00137 }
00138 if (!has_initialized_)
00139 {
00140 std::vector<boost::shared_ptr<diagnostic_msgs::DiagnosticStatus> > vec;
00141 return vec;
00142 }
00143
00144 boost::shared_ptr<diagnostic_msgs::DiagnosticStatus> header_status(new diagnostic_msgs::DiagnosticStatus());
00145 header_status->name = path_;
00146 header_status->level = 0;
00147 header_status->message = "OK";
00148
00149 std::vector<boost::shared_ptr<diagnostic_msgs::DiagnosticStatus> > processed;
00150 processed.push_back(header_status);
00151
00152 bool all_stale = true;
00153
00154 std::map<std::string, boost::shared_ptr<StatusItem> >::iterator it = items_.begin();
00155 while(it != items_.end())
00156 {
00157 std::string name = it->first;
00158 boost::shared_ptr<StatusItem> item = it->second;
00159
00160 bool stale = false;
00161 if (timeout_ > 0)
00162 stale = (ros::Time::now() - item->getLastUpdateTime()).toSec() > timeout_;
00163
00164
00165 if (discard_stale_ && stale)
00166 {
00167 items_.erase(it++);
00168 continue;
00169 }
00170
00171 int8_t level = item->getLevel();
00172 header_status->level = std::max(header_status->level, level);
00173
00174 diagnostic_msgs::KeyValue kv;
00175 kv.key = name;
00176 kv.value = item->getMessage();
00177
00178 header_status->values.push_back(kv);
00179
00180 all_stale = all_stale && ((level == 3) || stale);
00181
00182
00183
00184 processed.push_back(item->toStatusMsg(path_, stale));
00185
00186 if (stale)
00187 header_status->level = 3;
00188
00189 ++it;
00190 }
00191
00192
00193 if (all_stale)
00194 header_status->level = 3;
00195 else if (header_status->level == 3)
00196 header_status->level = 2;
00197
00198 header_status->message = valToMsg(header_status->level);
00199
00200
00201 if (num_items_expected_ == 0 && items_.size() == 0)
00202 {
00203 header_status->level = 0;
00204 header_status->message = "OK";
00205 }
00206 else if (num_items_expected_ > 0 && int(items_.size()) != num_items_expected_)
00207 {
00208 int8_t lvl = 2;
00209 header_status->level = std::max(lvl, header_status->level);
00210
00211 std::stringstream expec, item;
00212 expec << num_items_expected_;
00213 item << items_.size();
00214
00215 if (items_.size() > 0)
00216 header_status->message = "Expected " + expec.str() + ", found " + item.str();
00217 else
00218 header_status->message = "No items found, expected " + expec.str();
00219 }
00220
00221 bool header_stale_timed_out = false;
00222 if (timeout_ > 0 && last_header_level_ == 3)
00223 header_stale_timed_out = (ros::Time::now() - last_header_status_change_).toSec() > timeout_;
00224
00225 if (last_header_level_ != header_status->level)
00226 {
00227 last_header_status_change_ = ros::Time::now();
00228 last_header_level_ = header_status->level;
00229 }
00230
00231 if (discard_stale_ && processed.size() == 1 && header_stale_timed_out)
00232 {
00233 std::vector<boost::shared_ptr<diagnostic_msgs::DiagnosticStatus> > vec;
00234 return vec;
00235 }
00236
00237 return processed;
00238 }
00239
00243 virtual bool match(const std::string name) = 0;
00244
00248 virtual std::string getPath() const { return path_; }
00249
00253 virtual std::string getName() const { return nice_name_; }
00254
00255 protected:
00256 std::string nice_name_;
00257 std::string path_;
00258
00259 double timeout_;
00260 int num_items_expected_;
00261
00265 void addItem(std::string name, boost::shared_ptr<StatusItem> item) { items_[name] = item; }
00266
00267 private:
00271 std::map<std::string, boost::shared_ptr<StatusItem> > items_;
00272
00273 bool discard_stale_, has_initialized_, has_warned_;
00274 ros::Time last_header_status_change_;
00275 int last_header_level_;
00276
00277 };
00278
00279 }
00280 #endif //GENERIC_ANALYZER_BASE_H