00001
00034 #include <string>
00035 #include <sys/types.h>
00036 #include <ifaddrs.h>
00037 #include <unistd.h>
00038
00039 #include "boost/algorithm/string/predicate.hpp"
00040 #include "diagnostic_updater/update_functions.h"
00041 #include "ridgeback_base/ridgeback_diagnostic_updater.h"
00042
00043 namespace ridgeback_base
00044 {
00045
00046 RidgebackDiagnosticUpdater::RidgebackDiagnosticUpdater()
00047 {
00048 setHardwareID("unknown");
00049 gethostname(hostname_, 1024);
00050
00051 add("General", this, &RidgebackDiagnosticUpdater::generalDiagnostics);
00052 add("Battery", this, &RidgebackDiagnosticUpdater::batteryDiagnostics);
00053 add("User voltage supplies", this, &RidgebackDiagnosticUpdater::voltageDiagnostics);
00054 add("Current consumption", this, &RidgebackDiagnosticUpdater::currentDiagnostics);
00055 add("Power consumption", this, &RidgebackDiagnosticUpdater::powerDiagnostics);
00056 add("Temperature", this, &RidgebackDiagnosticUpdater::temperatureDiagnostics);
00057
00058
00059 status_sub_ = nh_.subscribe("mcu/status", 5, &RidgebackDiagnosticUpdater::statusCallback, this);
00060
00061
00062 ros::param::param("~expected_imu_frequency", expected_imu_frequency_, 50.0);
00063 imu_diagnostic_ = new diagnostic_updater::TopicDiagnostic("/imu/data_raw", *this,
00064 diagnostic_updater::FrequencyStatusParam(&expected_imu_frequency_, &expected_imu_frequency_, 0.15),
00065 diagnostic_updater::TimeStampStatusParam(-1, 1.0));
00066 imu_sub_ = nh_.subscribe("/imu/data_raw", 5, &RidgebackDiagnosticUpdater::imuCallback, this);
00067
00068
00069 ros::param::param<std::string>("~wireless_interface", wireless_interface_, "wlan0");
00070 ROS_INFO_STREAM("Checking for wireless connectivity on interface: " << wireless_interface_);
00071 wifi_connected_pub_ = nh_.advertise<std_msgs::Bool>("wifi_connected", 1);
00072 wireless_monitor_timer_ =
00073 nh_.createTimer(ros::Duration(1.0), &RidgebackDiagnosticUpdater::wirelessMonitorCallback, this);
00074 }
00075
00076 void RidgebackDiagnosticUpdater::generalDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
00077 {
00078 stat.addf("MCU uptime", "%d seconds", last_status_->mcu_uptime.toSec());
00079 stat.add("External stop status", last_status_->external_stop_present ? "present" : "absent");
00080 stat.add("Run/stop status", last_status_->external_stop_present ? "running" : "stopped");
00081
00082 if (!last_status_->drivers_active)
00083 {
00084 stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Stop loop open, platform immobilized.");
00085 }
00086 else
00087 {
00088 stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "System OK.");
00089 }
00090 }
00091
00092 void RidgebackDiagnosticUpdater::batteryDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
00093 {
00094 stat.add("Battery Voltage (V)", last_status_->measured_battery);
00095
00096 if (last_status_->measured_battery > 30.0)
00097 {
00098 stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Battery overvoltage.");
00099 }
00100 else if (last_status_->measured_battery < 1.0)
00101 {
00102 stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Battery voltage not detected, check BATT fuse.");
00103 }
00104 else if (last_status_->measured_battery < 20.0)
00105 {
00106 stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Battery critically under voltage.");
00107 }
00108 else if (last_status_->measured_battery < 24.0)
00109 {
00110 stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Battery low voltage.");
00111 }
00112 else
00113 {
00114 stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Battery OK.");
00115 }
00116 }
00117
00118 void RidgebackDiagnosticUpdater::voltageDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
00119 {
00120 stat.add("12V Supply (V)", last_status_->measured_12v);
00121 stat.add("5V Supply (V)", last_status_->measured_5v);
00122
00123 if (last_status_->measured_12v > 12.5 || last_status_->measured_5v > 5.5)
00124 {
00125 stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR,
00126 "User supply overvoltage. Accessories may be damaged.");
00127 }
00128 else if (last_status_->measured_12v < 1.0 || last_status_->measured_5v < 1.0)
00129 {
00130 stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "User supplies absent. Check tray fuses.");
00131 }
00132 else if (last_status_->measured_12v < 11.0 || last_status_->measured_5v < 4.0)
00133 {
00134 stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Voltage supplies undervoltage. Check loading levels.");
00135 }
00136 else
00137 {
00138 stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "User supplies OK.");
00139 }
00140 }
00141
00142 void RidgebackDiagnosticUpdater::currentDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
00143 {
00144 stat.add("Total current (A)", last_status_->total_current);
00145
00146 if (last_status_->total_current > 32.0)
00147 {
00148 stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Current draw critical.");
00149 }
00150 else if (last_status_->total_current > 20.0)
00151 {
00152 stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Current draw warning.");
00153 }
00154 else if (last_status_->total_current > 10.0)
00155 {
00156 stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Current draw requires monitoring.");
00157 }
00158 else
00159 {
00160 stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Current draw nominal.");
00161 }
00162 }
00163
00164 void RidgebackDiagnosticUpdater::powerDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
00165 {
00166 stat.add("Total power consumption (Wh)", last_status_->total_power_consumed);
00167 stat.add("AC power connnected", last_status_->charger_connected);
00168
00169 if (last_status_->total_power_consumed > 260.0)
00170 {
00171 stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Power consumed exceeds capacity of standard battery.");
00172 }
00173 else if (last_status_->total_power_consumed > 220.0)
00174 {
00175 stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Power consumed approaches capacity of standard battery.");
00176 }
00177 else
00178 {
00179 stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Battery OK.");
00180 }
00181 }
00182
00183 void RidgebackDiagnosticUpdater::temperatureDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
00184 {
00185 stat.add("PCB temperature (C)", last_status_->pcb_temperature);
00186 stat.add("MCU temperature (C)", last_status_->mcu_temperature);
00187
00188 if (last_status_->pcb_temperature > 100.0)
00189 {
00190 stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "PCB temperature too HOT.");
00191 }
00192 else if (last_status_->pcb_temperature > 60.0)
00193 {
00194 stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "PCB temperature getting warm.");
00195 }
00196 else
00197 {
00198 stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "PCB temperature OK.");
00199 }
00200
00201 if (last_status_->mcu_temperature > 100.0)
00202 {
00203 stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "MCU temperature too HOT.");
00204 }
00205 else if (last_status_->mcu_temperature > 60.0)
00206 {
00207 stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "MCU temperature getting warm.");
00208 }
00209 else
00210 {
00211 stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "MCU temperature OK.");
00212 }
00213 }
00214
00215 void RidgebackDiagnosticUpdater::statusCallback(const ridgeback_msgs::Status::ConstPtr& status)
00216 {
00217
00218 last_status_ = status;
00219 setHardwareID(hostname_ + '-' + last_status_->hardware_id);
00220 update();
00221 }
00222
00223 void RidgebackDiagnosticUpdater::imuCallback(const sensor_msgs::Imu::ConstPtr& msg)
00224 {
00225 imu_diagnostic_->tick(msg->header.stamp);
00226 }
00227
00228 void RidgebackDiagnosticUpdater::wirelessMonitorCallback(const ros::TimerEvent& te)
00229 {
00230 std_msgs::Bool wifi_connected_msg;
00231 wifi_connected_msg.data = false;
00232
00233
00234 struct ifaddrs* ifa_head;
00235 if (getifaddrs(&ifa_head) != 0)
00236 {
00237 ROS_WARN("System call getifaddrs returned error code. Unable to detect network interfaces.");
00238 return;
00239 }
00240
00241
00242 struct ifaddrs* ifa_current = ifa_head;
00243 while (ifa_current != NULL)
00244 {
00245 if (strcmp(ifa_current->ifa_name, wireless_interface_.c_str()) == 0)
00246 {
00247 int family = ifa_current->ifa_addr->sa_family;
00248 if (family == AF_INET || family == AF_INET6)
00249 {
00250 wifi_connected_msg.data = true;
00251 break;
00252 }
00253 }
00254
00255 ifa_current = ifa_current->ifa_next;
00256 }
00257
00258
00259 freeifaddrs(ifa_head);
00260 wifi_connected_pub_.publish(wifi_connected_msg);
00261 }
00262
00263 }