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
00035
00036
00037
00038 #include "corobot_diagnostics/corobot_analyzer.h"
00039
00040
00041 PLUGINLIB_EXPORT_CLASS(diagnostic_aggregator::CorobotAnalyzer,
00042 diagnostic_aggregator::Analyzer)
00043
00044 using namespace diagnostic_aggregator;
00045 using namespace std;
00046
00047 CorobotAnalyzer::CorobotAnalyzer() { }
00048
00049 bool CorobotAnalyzer::init(const string base_path, const ros::NodeHandle &n)
00050 {
00051
00052 ros::NodeHandle nh;
00053 newError_pub = nh.advertise<std_msgs::String>("new_diagnostic_error", 1000);
00054 removeError_pub = nh.advertise<std_msgs::String>("remove_diagnostic_error", 1000);
00055
00056 string nice_name;
00057 if (!n.getParam("path", nice_name))
00058 {
00059 ROS_ERROR("GenericAnalyzer was not given parameter \"path\". Namepspace: %s",
00060 n.getNamespace().c_str());
00061 return false;
00062 }
00063
00064 XmlRpc::XmlRpcValue findRemove;
00065 if (n.getParam("find_and_remove_prefix", findRemove))
00066 {
00067 vector<string> output;
00068 getParamVals(findRemove, output);
00069 chaff_ = output;
00070 startswith_ = output;
00071 }
00072
00073 XmlRpc::XmlRpcValue removes;
00074 if (n.getParam("remove_prefix", removes))
00075 getParamVals(removes, chaff_);
00076
00077 XmlRpc::XmlRpcValue startswith;
00078 if (n.getParam("startswith", startswith))
00079 getParamVals(startswith, startswith_);
00080
00081 XmlRpc::XmlRpcValue name_val;
00082 if (n.getParam("name", name_val))
00083 getParamVals(name_val, name_);
00084
00085 XmlRpc::XmlRpcValue contains;
00086 if (n.getParam("contains", contains))
00087 getParamVals(contains, contains_);
00088
00089 XmlRpc::XmlRpcValue expected;
00090 if (n.getParam("expected", expected))
00091 {
00092 getParamVals(expected, expected_);
00093 for (unsigned int i = 0; i < expected_.size(); ++i)
00094 {
00095 boost::shared_ptr<StatusItem> item(new StatusItem(expected_[i]));
00096 addItem(expected_[i], item);
00097 }
00098 }
00099
00100 XmlRpc::XmlRpcValue regexes;
00101 if (n.getParam("regex", regexes))
00102 {
00103 vector<string> regex_strs;
00104 getParamVals(regexes, regex_strs);
00105
00106 for (unsigned int i = 0; i < regex_strs.size(); ++i)
00107 {
00108 try
00109 {
00110 boost::regex re(regex_strs[i]);
00111 regex_.push_back(re);
00112 }
00113 catch (boost::regex_error& e)
00114 {
00115 ROS_ERROR("Attempted to make regex from %s. Caught exception, ignoring value. Exception: %s",
00116 regex_strs[i].c_str(), e.what());
00117 }
00118 }
00119 }
00120
00121 if (startswith_.size() == 0 && name_.size() == 0 &&
00122 contains_.size() == 0 && expected_.size() == 0 && regex_.size() == 0)
00123 {
00124 ROS_ERROR("CorobotAnalyzer was not initialized with any way of checking diagnostics. Name: %s, namespace: %s", nice_name.c_str(), n.getNamespace().c_str());
00125 return false;
00126 }
00127
00128 double timeout;
00129 int num_items_expected;
00130 bool discard_stale;
00131 n.param("timeout", timeout, 5.0);
00132 n.param("num_items", num_items_expected, -1);
00133 n.param("discard_stale", discard_stale, false);
00134
00135
00136 string my_path;
00137 if (base_path == "/")
00138 my_path = nice_name;
00139 else
00140 my_path = base_path + "/" + nice_name;
00141
00142 if (my_path.find("/") != 0)
00143 my_path = "/" + my_path;
00144
00145
00146 return GenericAnalyzerBase::init(my_path, nice_name,
00147 timeout, num_items_expected, discard_stale);
00148 }
00149
00150 CorobotAnalyzer::~CorobotAnalyzer()
00151 {
00152
00153 }
00154
00155
00156 bool CorobotAnalyzer::match(const string name)
00157 {
00158 boost::cmatch what;
00159 for (unsigned int i = 0; i < regex_.size(); ++i)
00160 {
00161 if (boost::regex_match(name.c_str(), what, regex_[i]))
00162 return true;
00163 }
00164
00165 for (unsigned int i = 0; i < expected_.size(); ++i)
00166 {
00167 if (name == expected_[i])
00168 return true;
00169 }
00170
00171 for (unsigned int i = 0; i < name_.size(); ++i)
00172 {
00173 if (name == name_[i])
00174 return true;
00175 }
00176
00177 for (unsigned int i = 0; i < startswith_.size(); ++i)
00178 {
00179 if (name.find(startswith_[i]) == 0)
00180 return true;
00181 }
00182
00183 for (unsigned int i = 0; i < contains_.size(); ++i)
00184 {
00185 if (name.find(contains_[i]) != string::npos)
00186 return true;
00187 }
00188
00189 return false;
00190 }
00191
00192 void CorobotAnalyzer::processLCD(boost::shared_ptr<diagnostic_msgs::DiagnosticStatus> processed)
00193
00194 {
00195 std::string error;
00196
00197 if (processed->level > 0)
00198 {
00199 for (unsigned int k = 0; k < processed->values.size(); ++k)
00200 {
00201
00202 if(processed->values[k].key == "Recommendation")
00203 {
00204 error = processed->values[k].value;
00205 }
00206 }
00207 }
00208 if (processed->level == 3)
00209 {
00210
00211 error = processed->name + std::string(" is stalled");
00212 }
00213
00214
00215 for (int i=0; i < processErrorsList.size(); i++)
00216 {
00217 if (processErrorsList.at(i).processName.compare(processed->name) == 0 && (processErrorsList.at(i).level != processed->level || error.compare(processErrorsList.at(i).error) != 0))
00218 {
00219
00220 std_msgs::String msg;
00221 msg.data = processErrorsList.at(i).error;
00222 if(removeError_pub)
00223 removeError_pub.publish(msg);
00224
00225 processErrorsList.erase(processErrorsList.begin()+i);
00226 }
00227 }
00228 int k;
00229 for (k=0; k < processErrorsList.size(); k++)
00230
00231 {
00232 if (processErrorsList.at(k).processName.compare(processed->name) == 0)
00233 break;
00234 }
00235
00236
00237 if (processed->level != 0 && k==processErrorsList.size() && error.size() != 0 && newError_pub.getNumSubscribers() > 0)
00238 {
00239 struct processErrors perr;
00240 perr.error = error;
00241 perr.level = processed->level;
00242 perr.processName = processed->name;
00243 processErrorsList.push_back(perr);
00244
00245 std_msgs::String msg;
00246 msg.data = error;
00247 if(newError_pub)
00248 newError_pub.publish(msg);
00249 }
00250
00251 }
00252
00253
00254 vector<boost::shared_ptr<diagnostic_msgs::DiagnosticStatus> > CorobotAnalyzer::report()
00255 {
00256 vector<boost::shared_ptr<diagnostic_msgs::DiagnosticStatus> > processed = GenericAnalyzerBase::report();
00257
00258
00259
00260 for (unsigned int j = 0; j < processed.size(); ++j)
00261 {
00262 processLCD(processed[j]);
00263
00264 }
00265
00266
00267 vector<string> expected_names_missing;
00268 bool has_name = false;
00269 bool all_stale = true;
00270
00271 for (unsigned int i = 0; i < expected_.size(); ++i)
00272 {
00273 has_name = false;
00274 for (unsigned int j = 0; j < processed.size(); ++j)
00275 {
00276 if (!processed[j]->level == 3)
00277 all_stale = false;
00278
00279 size_t last_slash = processed[j]->name.rfind("/");
00280 string nice_name = processed[j]->name.substr(last_slash + 1);
00281 if (nice_name == expected_[i] || nice_name == getOutputName(expected_[i]))
00282 {
00283 has_name = true;
00284 break;
00285 }
00286
00287
00288 for (unsigned int k = 0; k < chaff_.size(); ++k)
00289 {
00290 if (nice_name == removeLeadingNameChaff(expected_[i], chaff_[k]))
00291 {
00292 has_name = true;
00293 break;
00294 }
00295 }
00296
00297 }
00298 if (!has_name)
00299 expected_names_missing.push_back(expected_[i]);
00300 }
00301
00302
00303 for (unsigned int i = 0; i < expected_names_missing.size(); ++i)
00304 {
00305 boost::shared_ptr<StatusItem> item(new StatusItem(expected_names_missing[i]));
00306 processed.push_back(item->toStatusMsg(path_, true));
00307 }
00308
00309
00310 for (unsigned int j = 0; j < processed.size(); ++j)
00311 {
00312 if (processed[j]->level != 3)
00313 all_stale = false;
00314
00315 }
00316
00317 for (unsigned int j = 0; j < processed.size(); ++j)
00318 {
00319
00320 for (unsigned int i = 0; i < chaff_.size(); ++i)
00321 processed[j]->name = removeLeadingNameChaff(processed[j]->name, chaff_[i]);
00322
00323
00324 if (expected_names_missing.size() > 0 && processed[j]->name == path_)
00325 {
00326 if (!all_stale)
00327 {
00328 processed[j]->level = 2;
00329 processed[j]->message = "Error";
00330 }
00331 else
00332 {
00333 processed[j]->level = 3;
00334 processed[j]->message = "All Stale";
00335 }
00336
00337
00338 for (unsigned int k = 0; k < expected_names_missing.size(); ++k)
00339 {
00340 diagnostic_msgs::KeyValue kv;
00341 kv.key = expected_names_missing[k];
00342 kv.value = "Missing";
00343 processed[j]->values.push_back(kv);
00344 }
00345 }
00346 }
00347
00348 return processed;
00349 }
00350