husky_diagnostics.cpp
Go to the documentation of this file.
1 
33 
34 namespace
35 {
36  const int UNDERVOLT_ERROR = 18;
37  const int UNDERVOLT_WARN = 19;
38  const int OVERVOLT_ERROR = 30;
39  const int OVERVOLT_WARN = 29;
40  const int DRIVER_OVERTEMP_ERROR = 50;
41  const int DRIVER_OVERTEMP_WARN = 30;
42  const int MOTOR_OVERTEMP_ERROR = 80;
43  const int MOTOR_OVERTEMP_WARN = 70;
44  const double LOWPOWER_ERROR = 0.2;
45  const double LOWPOWER_WARN = 0.3;
46  const int CONTROLFREQ_WARN = 90;
47  const unsigned int SAFETY_TIMEOUT = 0x1;
48  const unsigned int SAFETY_LOCKOUT = 0x2;
49  const unsigned int SAFETY_ESTOP = 0x8;
50  const unsigned int SAFETY_CCI = 0x10;
51  const unsigned int SAFETY_PSU = 0x20;
52  const unsigned int SAFETY_CURRENT = 0x40;
53  const unsigned int SAFETY_WARN = (SAFETY_TIMEOUT | SAFETY_CCI | SAFETY_PSU);
54  const unsigned int SAFETY_ERROR = (SAFETY_LOCKOUT | SAFETY_ESTOP | SAFETY_CURRENT);
55 } // namespace
56 
57 namespace husky_base
58 {
59 
60  template<>
62  :
63  DiagnosticTask("system_status"),
64  msg_(msg)
65  { }
66 
67  template<>
71  {
72  msg_.uptime = system_status->getUptime();
73 
74  msg_.battery_voltage = system_status->getVoltage(0);
75  msg_.left_driver_voltage = system_status->getVoltage(1);
76  msg_.right_driver_voltage = system_status->getVoltage(2);
77 
78  msg_.mcu_and_user_port_current = system_status->getCurrent(0);
79  msg_.left_driver_current = system_status->getCurrent(1);
80  msg_.right_driver_current = system_status->getCurrent(2);
81 
82  msg_.left_driver_temp = system_status->getTemperature(0);
83  msg_.right_driver_temp = system_status->getTemperature(1);
84  msg_.left_motor_temp = system_status->getTemperature(2);
85  msg_.right_motor_temp = system_status->getTemperature(3);
86 
87  stat.add("Uptime", msg_.uptime);
88 
89  stat.add("Battery Voltage", msg_.battery_voltage);
90  stat.add("Left Motor Driver Voltage", msg_.left_driver_voltage);
91  stat.add("Right Motor Driver Voltage", msg_.right_driver_voltage);
92 
93  stat.add("MCU and User Port Current", msg_.mcu_and_user_port_current);
94  stat.add("Left Motor Driver Current", msg_.left_driver_current);
95  stat.add("Right Motor Driver Current", msg_.right_driver_current);
96 
97  stat.add("Left Motor Driver Temp (C)", msg_.left_driver_temp);
98  stat.add("Right Motor Driver Temp (C)", msg_.right_driver_temp);
99  stat.add("Left Motor Temp (C)", msg_.left_motor_temp);
100  stat.add("Right Motor Temp (C)", msg_.right_motor_temp);
101 
102  stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "System Status OK");
103  if (msg_.battery_voltage > OVERVOLT_ERROR)
104  {
105  stat.mergeSummary(diagnostic_msgs::DiagnosticStatus::ERROR, "Main battery voltage too high");
106  }
107  else if (msg_.battery_voltage > OVERVOLT_WARN)
108  {
109  stat.mergeSummary(diagnostic_msgs::DiagnosticStatus::WARN, "Main battery voltage too high");
110  }
111  else if (msg_.battery_voltage < UNDERVOLT_ERROR)
112  {
113  stat.mergeSummary(diagnostic_msgs::DiagnosticStatus::ERROR, "Main battery voltage too low");
114  }
115  else if (msg_.battery_voltage < UNDERVOLT_WARN)
116  {
117  stat.mergeSummary(diagnostic_msgs::DiagnosticStatus::WARN, "Main battery voltage too low");
118  }
119  else
120  {
121  stat.mergeSummary(diagnostic_msgs::DiagnosticStatus::OK, "Voltage OK");
122  }
123 
124  if (std::max(msg_.left_driver_temp, msg_.right_driver_temp) > DRIVER_OVERTEMP_ERROR)
125  {
126  stat.mergeSummary(diagnostic_msgs::DiagnosticStatus::ERROR, "Motor drivers too hot");
127  }
128  else if (std::max(msg_.left_driver_temp, msg_.right_driver_temp) > DRIVER_OVERTEMP_WARN)
129  {
130  stat.mergeSummary(diagnostic_msgs::DiagnosticStatus::WARN, "Motor drivers too hot");
131  }
132  else if (std::max(msg_.left_motor_temp, msg_.right_motor_temp) > MOTOR_OVERTEMP_ERROR)
133  {
134  stat.mergeSummary(diagnostic_msgs::DiagnosticStatus::ERROR, "Motors too hot");
135  }
136  else if (std::max(msg_.left_motor_temp, msg_.right_motor_temp) > MOTOR_OVERTEMP_WARN)
137  {
138  stat.mergeSummary(diagnostic_msgs::DiagnosticStatus::WARN, "Motors too hot");
139  }
140  else
141  {
142  stat.mergeSummary(diagnostic_msgs::DiagnosticStatus::OK, "Temperature OK");
143  }
144  }
145 
146  template<>
148  :
149  DiagnosticTask("power_status"),
150  msg_(msg)
151  { }
152 
153  template<>
157  {
158  msg_.charge_estimate = power_status->getChargeEstimate(0);
159  msg_.capacity_estimate = power_status->getCapacityEstimate(0);
160 
161  stat.add("Charge (%)", msg_.charge_estimate);
162  stat.add("Battery Capacity (Wh)", msg_.capacity_estimate);
163 
164  stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Power System OK");
165  if (msg_.charge_estimate < LOWPOWER_ERROR)
166  {
167  stat.mergeSummary(diagnostic_msgs::DiagnosticStatus::ERROR, "Low power");
168  }
169  else if (msg_.charge_estimate < LOWPOWER_WARN)
170  {
171  stat.mergeSummary(diagnostic_msgs::DiagnosticStatus::WARN, "Low power");
172  }
173  else
174  {
175  stat.mergeSummary(diagnostic_msgs::DiagnosticStatus::OK, "Charge OK");
176  }
177  }
178 
179  template<>
181  husky_msgs::HuskyStatus &msg)
182  :
183  DiagnosticTask("safety_status"),
184  msg_(msg)
185  { }
186 
187  template<>
191  {
192  uint16_t flags = safety_status->getFlags();
193  msg_.timeout = (flags & SAFETY_TIMEOUT) > 0;
194  msg_.lockout = (flags & SAFETY_LOCKOUT) > 0;
195  msg_.e_stop = (flags & SAFETY_ESTOP) > 0;
196  msg_.ros_pause = (flags & SAFETY_CCI) > 0;
197  msg_.no_battery = (flags & SAFETY_PSU) > 0;
198  msg_.current_limit = (flags & SAFETY_CURRENT) > 0;
199 
200  stat.add("Timeout", static_cast<bool>(msg_.timeout));
201  stat.add("Lockout", static_cast<bool>(msg_.lockout));
202  stat.add("Emergency Stop", static_cast<bool>(msg_.e_stop));
203  stat.add("ROS Pause", static_cast<bool>(msg_.ros_pause));
204  stat.add("No battery", static_cast<bool>(msg_.no_battery));
205  stat.add("Current limit", static_cast<bool>(msg_.current_limit));
206 
207  stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Safety System OK");
208  if ((flags & SAFETY_ERROR) > 0)
209  {
210  stat.mergeSummary(diagnostic_msgs::DiagnosticStatus::ERROR, "Safety System Error");
211  }
212  else if ((flags & SAFETY_WARN) > 0)
213  {
214  stat.mergeSummary(diagnostic_msgs::DiagnosticStatus::WARN, "Safety System Warning");
215  }
216  }
217 
218  HuskySoftwareDiagnosticTask::HuskySoftwareDiagnosticTask(husky_msgs::HuskyStatus &msg, double target_control_freq)
219  :
220  DiagnosticTask("software_status"),
221  msg_(msg),
222  target_control_freq_(target_control_freq)
223  {
224  reset();
225  }
226 
228  {
229  // Keep minimum observed frequency for diagnostics purposes
230  control_freq_ = std::min(control_freq_, frequency);
231  }
232 
234  {
235  msg_.ros_control_loop_freq = control_freq_;
236  stat.add("ROS Control Loop Frequency", msg_.ros_control_loop_freq);
237 
238  double margin = control_freq_ / target_control_freq_ * 100;
239 
240  stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Software OK");
241  if (margin < CONTROLFREQ_WARN)
242  {
243  std::ostringstream message;
244  message << "Control loop executing " << 100 - static_cast<int>(margin) << "% slower than desired";
245  stat.mergeSummary(diagnostic_msgs::DiagnosticStatus::WARN, message.str());
246  }
247 
248  reset();
249  }
250 
252  {
253  control_freq_ = std::numeric_limits<double>::infinity();
255  }
256 } // namespace husky_base
void run(diagnostic_updater::DiagnosticStatusWrapper &stat)
HuskyHardwareDiagnosticTask(husky_msgs::HuskyStatus &msg)
void summary(unsigned char lvl, const std::string s)
void update(diagnostic_updater::DiagnosticStatusWrapper &stat, typename horizon_legacy::Channel< T >::Ptr &status)
def message(msg, args, kwargs)
void mergeSummary(unsigned char lvl, const std::string s)
DiagnosticTask(const std::string name)
void add(const std::string &key, const T &val)
HuskySoftwareDiagnosticTask(husky_msgs::HuskyStatus &msg, double target_control_freq)


husky_base
Author(s): Mike Purvis , Paul Bovbel
autogenerated on Fri Oct 2 2020 03:40:07