jackal_diagnostic_updater.cpp
Go to the documentation of this file.
00001 
00034 #include <string>
00035 #include <sys/types.h>
00036 #include <ifaddrs.h>
00037 
00038 #include "boost/algorithm/string/predicate.hpp"
00039 #include "diagnostic_updater/update_functions.h"
00040 #include "jackal_base/jackal_diagnostic_updater.h"
00041 
00042 
00043 namespace jackal_base
00044 {
00045 
00046 JackalDiagnosticUpdater::JackalDiagnosticUpdater()
00047 {
00048   setHardwareID("unknown");
00049 
00050   add("General", this, &JackalDiagnosticUpdater::generalDiagnostics);
00051   add("Battery", this, &JackalDiagnosticUpdater::batteryDiagnostics);
00052   add("User voltage supplies", this, &JackalDiagnosticUpdater::voltageDiagnostics);
00053   add("Current consumption", this, &JackalDiagnosticUpdater::currentDiagnostics);
00054   add("Power consumption", this, &JackalDiagnosticUpdater::powerDiagnostics);
00055 
00056   // The arrival of this message runs the update() method and triggers the above callbacks.
00057   status_sub_ = nh_.subscribe("status", 5, &JackalDiagnosticUpdater::statusCallback, this);
00058 
00059   // These message frequencies are reported on separately.
00060   ros::param::param("~expected_imu_frequency", expected_imu_frequency_, 50.0);
00061   imu_diagnostic_ = new diagnostic_updater::TopicDiagnostic("/imu/data_raw", *this,
00062       diagnostic_updater::FrequencyStatusParam(&expected_imu_frequency_, &expected_imu_frequency_, 0.15),
00063       diagnostic_updater::TimeStampStatusParam(-1, 1.0));
00064   imu_sub_ = nh_.subscribe("/imu/data_raw", 5, &JackalDiagnosticUpdater::imuCallback, this);
00065 
00066   ros::param::param("~expected_navsat_frequency", expected_navsat_frequency_, 10.0);
00067   ros::param::param<std::string>("~navsat_frequency_sentence", navsat_frequency_sentence_, "$GPRMC");
00068   navsat_diagnostic_ = new diagnostic_updater::TopicDiagnostic("/navsat/nmea_sentence", *this,
00069       diagnostic_updater::FrequencyStatusParam(&expected_navsat_frequency_, &expected_navsat_frequency_, 0.1),
00070       diagnostic_updater::TimeStampStatusParam(-1, 1.0));
00071   navsat_sub_ = nh_.subscribe("/navsat/nmea_sentence", 5, &JackalDiagnosticUpdater::navsatCallback, this);
00072 
00073   // Publish whether the wireless interface has an IP address every second.
00074   ros::param::param<std::string>("~wireless_interface", wireless_interface_, "wlan0");
00075   ROS_INFO_STREAM("Checking for wireless connectivity on interface: " << wireless_interface_);
00076   wifi_connected_pub_ = nh_.advertise<std_msgs::Bool>("wifi_connected", 1);
00077   wireless_monitor_timer_ = nh_.createTimer(ros::Duration(1.0),
00078       &JackalDiagnosticUpdater::wirelessMonitorCallback, this);
00079 }
00080 
00081 void JackalDiagnosticUpdater::generalDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
00082 {
00083   stat.add("MCU uptime (s)", last_status_->mcu_uptime.toSec());
00084   stat.addf("Motor drivers energized", "%s", last_status_->drivers_active ? "true" : "false");
00085 
00086   if (last_status_->driver_external_stop_present)
00087   {
00088     if (last_status_->driver_external_stop_stopped)
00089     {
00090       stat.add("External stop", "Present, asserting stop");
00091     }
00092     else
00093     {
00094       stat.add("External stop", "Present, not asserting stop");
00095     }
00096   }
00097   else
00098   {
00099     stat.add("External stop", "Absent");
00100   }
00101 
00102   if (last_status_->driver_external_stop_stopped)
00103   {
00104     stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "External stop device asserting motor stop.");
00105   }
00106   else if (!last_status_->drivers_active)
00107   {
00108     stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Motor drivers not energized.");
00109   }
00110   else
00111   {
00112     stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "System OK.");
00113   }
00114 }
00115 
00116 void JackalDiagnosticUpdater::batteryDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
00117 {
00118   stat.add("Battery Voltage (V)", last_status_->measured_battery);
00119 
00120   if (last_status_->measured_battery > 30.0)
00121   {
00122     stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Battery overvoltage.");
00123   }
00124   else if (last_status_->measured_battery < 1.0)
00125   {
00126     stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Battery voltage not detected, check BATT fuse.");
00127   }
00128   else if (last_status_->measured_battery < 20.0)
00129   {
00130     stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Battery critically under voltage.");
00131   }
00132   else if (last_status_->measured_battery < 24.0)
00133   {
00134     stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Battery low voltage.");
00135   }
00136   else
00137   {
00138     stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Battery OK.");
00139   }
00140 }
00141 
00142 void JackalDiagnosticUpdater::voltageDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
00143 {
00144   stat.add("12V Supply (V)", last_status_->measured_12v);
00145   stat.add("5V Supply (V)", last_status_->measured_5v);
00146 
00147   if (last_status_->measured_12v > 12.5 || last_status_->measured_5v > 5.5)
00148   {
00149     stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR,
00150         "User supply overvoltage. Accessories may be damaged.");
00151   }
00152   else if (last_status_->measured_12v < 1.0 || last_status_->measured_5v < 1.0)
00153   {
00154     stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "User supplies absent. Check tray fuses.");
00155   }
00156   else if (last_status_->measured_12v < 11.0 || last_status_->measured_5v < 4.0)
00157   {
00158     stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Voltage supplies undervoltage. Check loading levels.");
00159   }
00160   else
00161   {
00162     stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "User supplies OK.");
00163   }
00164 }
00165 
00166 void JackalDiagnosticUpdater::currentDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
00167 {
00168   stat.add("Drive current (A)", last_status_->drive_current);
00169   stat.add("User current (A)", last_status_->user_current);
00170   stat.add("Computer current (A)", last_status_->computer_current);
00171   stat.add("Total current (A)", last_status_->total_current);
00172 
00173   if (last_status_->total_current > 32.0)
00174   {
00175     stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Current draw critical.");
00176   }
00177   else if (last_status_->total_current > 20.0)
00178   {
00179     stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Current draw warning.");
00180   }
00181   else if (last_status_->total_current > 10.0)
00182   {
00183     stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Current draw requires monitoring.");
00184   }
00185   else
00186   {
00187     stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Current draw nominal.");
00188   }
00189 }
00190 
00191 void JackalDiagnosticUpdater::powerDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
00192 {
00193   stat.add("Total power consumption (Wh)", last_status_->total_power_consumed);
00194 
00195   if (last_status_->total_power_consumed > 260.0)
00196   {
00197     stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Power consumed exceeds capacity of standard battery.");
00198   }
00199   else if (last_status_->total_power_consumed > 220.0)
00200   {
00201     stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Power consumed approaches capacity of standard battery.");
00202   }
00203   else
00204   {
00205     stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Battery OK.");
00206   }
00207 }
00208 
00209 void JackalDiagnosticUpdater::statusCallback(const jackal_msgs::Status::ConstPtr& status)
00210 {
00211   // Fresh data from the MCU, publish a diagnostic update.
00212   last_status_ = status;
00213   setHardwareID(last_status_->hardware_id);
00214   update();
00215 }
00216 
00217 void JackalDiagnosticUpdater::imuCallback(const sensor_msgs::Imu::ConstPtr& msg)
00218 {
00219   imu_diagnostic_->tick(msg->header.stamp);
00220 }
00221 
00222 void JackalDiagnosticUpdater::navsatCallback(const nmea_msgs::Sentence::ConstPtr& msg)
00223 {
00224   if (boost::starts_with(msg->sentence, navsat_frequency_sentence_))
00225   {
00226     navsat_diagnostic_->tick(msg->header.stamp);
00227   }
00228 }
00229 
00230 void JackalDiagnosticUpdater::wirelessMonitorCallback(const ros::TimerEvent& te)
00231 {
00232   std_msgs::Bool wifi_connected_msg;
00233   wifi_connected_msg.data = false;
00234 
00235   // Get system structure of interface IP addresses.
00236   struct ifaddrs* ifa_head;
00237   if (getifaddrs(&ifa_head) != 0)
00238   {
00239     ROS_WARN("System call getifaddrs returned error code. Unable to detect network interfaces.");
00240     return;
00241   }
00242 
00243   // Iterate structure looking for the wireless interface.
00244   struct ifaddrs* ifa_current = ifa_head;
00245   while (ifa_current != NULL)
00246   {
00247     if (strcmp(ifa_current->ifa_name, wireless_interface_.c_str()) == 0)
00248     {
00249       int family = ifa_current->ifa_addr->sa_family;
00250       if (family == AF_INET || family == AF_INET6)
00251       {
00252         wifi_connected_msg.data = true;
00253         break;
00254       }
00255     }
00256 
00257     ifa_current = ifa_current->ifa_next;
00258   }
00259 
00260   // Free structure, publish result message.
00261   freeifaddrs(ifa_head);
00262   wifi_connected_pub_.publish(wifi_connected_msg);
00263 }
00264 
00265 }  // namespace jackal_base


jackal_base
Author(s): Mike Purvis
autogenerated on Thu Jul 4 2019 19:48:56