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 #include "diagnostic_aggregator/generic_analyzer.h"
00038
00039 using namespace diagnostic_aggregator;
00040 using namespace std;
00041
00042 PLUGINLIB_DECLARE_CLASS(diagnostic_aggregator,
00043 GenericAnalyzer,
00044 diagnostic_aggregator::GenericAnalyzer,
00045 diagnostic_aggregator::Analyzer)
00046
00047
00048 GenericAnalyzer::GenericAnalyzer() { }
00049
00050 bool GenericAnalyzer::init(const string base_path, const ros::NodeHandle &n)
00051 {
00052 string nice_name;
00053 if (!n.getParam("path", nice_name))
00054 {
00055 ROS_ERROR("GenericAnalyzer was not given parameter \"path\". Namepspace: %s",
00056 n.getNamespace().c_str());
00057 return false;
00058 }
00059
00060 XmlRpc::XmlRpcValue findRemove;
00061 if (n.getParam("find_and_remove_prefix", findRemove))
00062 {
00063 vector<string> output;
00064 getParamVals(findRemove, output);
00065 chaff_ = output;
00066 startswith_ = output;
00067 }
00068
00069 XmlRpc::XmlRpcValue removes;
00070 if (n.getParam("remove_prefix", removes))
00071 getParamVals(removes, chaff_);
00072
00073 XmlRpc::XmlRpcValue startswith;
00074 if (n.getParam("startswith", startswith))
00075 getParamVals(startswith, startswith_);
00076
00077 XmlRpc::XmlRpcValue name_val;
00078 if (n.getParam("name", name_val))
00079 getParamVals(name_val, name_);
00080
00081 XmlRpc::XmlRpcValue contains;
00082 if (n.getParam("contains", contains))
00083 getParamVals(contains, contains_);
00084
00085 XmlRpc::XmlRpcValue expected;
00086 if (n.getParam("expected", expected))
00087 {
00088 getParamVals(expected, expected_);
00089 for (unsigned int i = 0; i < expected_.size(); ++i)
00090 {
00091 boost::shared_ptr<StatusItem> item(new StatusItem(expected_[i]));
00092 addItem(expected_[i], item);
00093 }
00094 }
00095
00096 XmlRpc::XmlRpcValue regexes;
00097 if (n.getParam("regex", regexes))
00098 {
00099 vector<string> regex_strs;
00100 getParamVals(regexes, regex_strs);
00101
00102 for (unsigned int i = 0; i < regex_strs.size(); ++i)
00103 {
00104 try
00105 {
00106 boost::regex re(regex_strs[i]);
00107 regex_.push_back(re);
00108 }
00109 catch (boost::regex_error& e)
00110 {
00111 ROS_ERROR("Attempted to make regex from %s. Caught exception, ignoring value. Exception: %s",
00112 regex_strs[i].c_str(), e.what());
00113 }
00114 }
00115 }
00116
00117 if (startswith_.size() == 0 && name_.size() == 0 &&
00118 contains_.size() == 0 && expected_.size() == 0 && regex_.size() == 0)
00119 {
00120 ROS_ERROR("GenericAnalyzer was not initialized with any way of checking diagnostics. Name: %s, namespace: %s", nice_name.c_str(), n.getNamespace().c_str());
00121 return false;
00122 }
00123
00124 double timeout;
00125 int num_items_expected;
00126 bool discard_stale;
00127 n.param("timeout", timeout, 5.0);
00128 n.param("num_items", num_items_expected, -1);
00129 n.param("discard_stale", discard_stale, false);
00130
00131 string my_path;
00132 if (base_path == "/")
00133 my_path = nice_name;
00134 else
00135 my_path = base_path + "/" + nice_name;
00136
00137 if (my_path.find("/") != 0)
00138 my_path = "/" + my_path;
00139
00140 return GenericAnalyzerBase::init(my_path, nice_name,
00141 timeout, num_items_expected, discard_stale);
00142 }
00143
00144 GenericAnalyzer::~GenericAnalyzer() { }
00145
00146
00147 bool GenericAnalyzer::match(const string name)
00148 {
00149 boost::cmatch what;
00150 for (unsigned int i = 0; i < regex_.size(); ++i)
00151 {
00152 if (boost::regex_match(name.c_str(), what, regex_[i]))
00153 return true;
00154 }
00155
00156 for (unsigned int i = 0; i < expected_.size(); ++i)
00157 {
00158 if (name == expected_[i])
00159 return true;
00160 }
00161
00162 for (unsigned int i = 0; i < name_.size(); ++i)
00163 {
00164 if (name == name_[i])
00165 return true;
00166 }
00167
00168 for (unsigned int i = 0; i < startswith_.size(); ++i)
00169 {
00170 if (name.find(startswith_[i]) == 0)
00171 return true;
00172 }
00173
00174 for (unsigned int i = 0; i < contains_.size(); ++i)
00175 {
00176 if (name.find(contains_[i]) != string::npos)
00177 return true;
00178 }
00179
00180 return false;
00181 }
00182
00183 vector<boost::shared_ptr<diagnostic_msgs::DiagnosticStatus> > GenericAnalyzer::report()
00184 {
00185 vector<boost::shared_ptr<diagnostic_msgs::DiagnosticStatus> > processed = GenericAnalyzerBase::report();
00186
00187
00188 vector<string> expected_names_missing;
00189 bool has_name = false;
00190 bool all_stale = true;
00191
00192 for (unsigned int i = 0; i < expected_.size(); ++i)
00193 {
00194 has_name = false;
00195 for (unsigned int j = 0; j < processed.size(); ++j)
00196 {
00197 if (!processed[j]->level == 3)
00198 all_stale = false;
00199
00200 size_t last_slash = processed[j]->name.rfind("/");
00201 string nice_name = processed[j]->name.substr(last_slash + 1);
00202 if (nice_name == expected_[i] || nice_name == getOutputName(expected_[i]))
00203 {
00204 has_name = true;
00205 break;
00206 }
00207
00208
00209 for (unsigned int k = 0; k < chaff_.size(); ++k)
00210 {
00211 if (nice_name == removeLeadingNameChaff(expected_[i], chaff_[k]))
00212 {
00213 has_name = true;
00214 break;
00215 }
00216 }
00217
00218 }
00219 if (!has_name)
00220 expected_names_missing.push_back(expected_[i]);
00221 }
00222
00223
00224 for (unsigned int i = 0; i < expected_names_missing.size(); ++i)
00225 {
00226 boost::shared_ptr<StatusItem> item(new StatusItem(expected_names_missing[i]));
00227 processed.push_back(item->toStatusMsg(path_, true));
00228 }
00229
00230
00231 for (unsigned int j = 0; j < processed.size(); ++j)
00232 {
00233 if (processed[j]->level != 3)
00234 all_stale = false;
00235 }
00236
00237 for (unsigned int j = 0; j < processed.size(); ++j)
00238 {
00239
00240 for (unsigned int i = 0; i < chaff_.size(); ++i)
00241 processed[j]->name = removeLeadingNameChaff(processed[j]->name, chaff_[i]);
00242
00243
00244 if (expected_names_missing.size() > 0 && processed[j]->name == path_)
00245 {
00246 if (!all_stale)
00247 {
00248 processed[j]->level = 2;
00249 processed[j]->message = "Error";
00250 }
00251 else
00252 {
00253 processed[j]->level = 3;
00254 processed[j]->message = "All Stale";
00255 }
00256
00257
00258 for (unsigned int k = 0; k < expected_names_missing.size(); ++k)
00259 {
00260 diagnostic_msgs::KeyValue kv;
00261 kv.key = expected_names_missing[k];
00262 kv.value = "Missing";
00263 processed[j]->values.push_back(kv);
00264 }
00265 }
00266 }
00267
00268 return processed;
00269 }