sys_status.cpp
Go to the documentation of this file.
1 
9 /*
10  * Copyright 2013,2014,2015,2016 Vladimir Ermakov.
11  *
12  * This file is part of the mavros package and subject to the license terms
13  * in the top-level LICENSE file of the mavros repository.
14  * https://github.com/mavlink/mavros/tree/master/LICENSE.md
15  */
16 
17 #include <mavros/mavros_plugin.h>
18 
19 #include <mavros_msgs/State.h>
20 #include <mavros_msgs/ExtendedState.h>
21 #include <mavros_msgs/StreamRate.h>
22 #include <mavros_msgs/SetMode.h>
23 #include <mavros_msgs/CommandLong.h>
24 #include <mavros_msgs/StatusText.h>
25 #include <mavros_msgs/VehicleInfo.h>
26 #include <mavros_msgs/VehicleInfoGet.h>
27 #include <mavros_msgs/MessageInterval.h>
28 
29 
30 #ifdef HAVE_SENSOR_MSGS_BATTERYSTATE_MSG
31 #include <sensor_msgs/BatteryState.h>
32 using BatteryMsg = sensor_msgs::BatteryState;
33 #else
34 #include <mavros_msgs/BatteryStatus.h>
35 using BatteryMsg = mavros_msgs::BatteryStatus;
36 #endif
37 
38 namespace mavros {
39 namespace std_plugins {
40 using mavlink::common::MAV_TYPE;
41 using mavlink::common::MAV_AUTOPILOT;
42 using mavlink::common::MAV_STATE;
43 using utils::enum_value;
44 
51 {
52 public:
53  HeartbeatStatus(const std::string &name, size_t win_size) :
55  times_(win_size),
56  seq_nums_(win_size),
57  window_size_(win_size),
58  min_freq_(0.2),
59  max_freq_(100),
60  tolerance_(0.1),
61  autopilot(MAV_AUTOPILOT::GENERIC),
62  type(MAV_TYPE::GENERIC),
63  system_status(MAV_STATE::UNINIT)
64  {
65  clear();
66  }
67 
68  void clear()
69  {
70  std::lock_guard<std::mutex> lock(mutex);
71  ros::Time curtime = ros::Time::now();
72  count_ = 0;
73 
74  for (size_t i = 0; i < window_size_; i++) {
75  times_[i] = curtime;
76  seq_nums_[i] = count_;
77  }
78 
79  hist_indx_ = 0;
80  }
81 
82  void tick(uint8_t type_, uint8_t autopilot_,
83  std::string &mode_, uint8_t system_status_)
84  {
85  std::lock_guard<std::mutex> lock(mutex);
86  count_++;
87 
88  type = static_cast<MAV_TYPE>(type_);
89  autopilot = static_cast<MAV_AUTOPILOT>(autopilot_);
90  mode = mode_;
91  system_status = static_cast<MAV_STATE>(system_status_);
92  }
93 
95  {
96  std::lock_guard<std::mutex> lock(mutex);
97 
98  ros::Time curtime = ros::Time::now();
99  int curseq = count_;
100  int events = curseq - seq_nums_[hist_indx_];
101  double window = (curtime - times_[hist_indx_]).toSec();
102  double freq = events / window;
103  seq_nums_[hist_indx_] = curseq;
104  times_[hist_indx_] = curtime;
106 
107  if (events == 0) {
108  stat.summary(2, "No events recorded.");
109  }
110  else if (freq < min_freq_ * (1 - tolerance_)) {
111  stat.summary(1, "Frequency too low.");
112  }
113  else if (freq > max_freq_ * (1 + tolerance_)) {
114  stat.summary(1, "Frequency too high.");
115  }
116  else {
117  stat.summary(0, "Normal");
118  }
119 
120  stat.addf("Heartbeats since startup", "%d", count_);
121  stat.addf("Frequency (Hz)", "%f", freq);
122  stat.add("Vehicle type", utils::to_string(type));
123  stat.add("Autopilot type", utils::to_string(autopilot));
124  stat.add("Mode", mode);
125  stat.add("System status", utils::to_string(system_status));
126  }
127 
128 private:
129  int count_;
130  std::vector<ros::Time> times_;
131  std::vector<int> seq_nums_;
134  const size_t window_size_;
135  const double min_freq_;
136  const double max_freq_;
137  const double tolerance_;
138 
139  MAV_AUTOPILOT autopilot;
141  std::string mode;
143 };
144 
145 
150 {
151 public:
152  SystemStatusDiag(const std::string &name) :
154  last_st {}
155  { }
156 
157  void set(mavlink::common::msg::SYS_STATUS &st)
158  {
159  std::lock_guard<std::mutex> lock(mutex);
160  last_st = st;
161  }
162 
164  std::lock_guard<std::mutex> lock(mutex);
165 
166  if ((last_st.onboard_control_sensors_health & last_st.onboard_control_sensors_enabled)
167  != last_st.onboard_control_sensors_enabled)
168  stat.summary(2, "Sensor health");
169  else
170  stat.summary(0, "Normal");
171 
172  stat.addf("Sensor present", "0x%08X", last_st.onboard_control_sensors_present);
173  stat.addf("Sensor enabled", "0x%08X", last_st.onboard_control_sensors_enabled);
174  stat.addf("Sensor health", "0x%08X", last_st.onboard_control_sensors_health);
175 
176  using STS = mavlink::common::MAV_SYS_STATUS_SENSOR;
177 
178  // [[[cog:
179  // import pymavlink.dialects.v20.common as common
180  // ename = 'MAV_SYS_STATUS_SENSOR'
181  // ename_pfx2 = 'MAV_SYS_STATUS_'
182  //
183  // enum = sorted(common.enums[ename].items())
184  // enum.pop() # -> remove ENUM_END
185  //
186  // for k, e in enum:
187  // desc = e.description.split(' ', 1)[1] if e.description.startswith('0x') else e.description
188  // sts = e.name
189  //
190  // if sts.startswith(ename + '_'):
191  // sts = sts[len(ename) + 1:]
192  // if sts.startswith(ename_pfx2):
193  // sts = sts[len(ename_pfx2):]
194  // if sts[0].isdigit():
195  // sts = 'SENSOR_' + sts
196  //
197  // cog.outl(f"""\
198  // if (last_st.onboard_control_sensors_enabled & enum_value(STS::{sts}))
199  // \tstat.add("{desc.strip()}", (last_st.onboard_control_sensors_health & enum_value(STS::{sts})) ? "Ok" : "Fail");""")
200  // ]]]
201  if (last_st.onboard_control_sensors_enabled & enum_value(STS::SENSOR_3D_GYRO))
202  stat.add("3D gyro", (last_st.onboard_control_sensors_health & enum_value(STS::SENSOR_3D_GYRO)) ? "Ok" : "Fail");
203  if (last_st.onboard_control_sensors_enabled & enum_value(STS::SENSOR_3D_ACCEL))
204  stat.add("3D accelerometer", (last_st.onboard_control_sensors_health & enum_value(STS::SENSOR_3D_ACCEL)) ? "Ok" : "Fail");
205  if (last_st.onboard_control_sensors_enabled & enum_value(STS::SENSOR_3D_MAG))
206  stat.add("3D magnetometer", (last_st.onboard_control_sensors_health & enum_value(STS::SENSOR_3D_MAG)) ? "Ok" : "Fail");
207  if (last_st.onboard_control_sensors_enabled & enum_value(STS::ABSOLUTE_PRESSURE))
208  stat.add("absolute pressure", (last_st.onboard_control_sensors_health & enum_value(STS::ABSOLUTE_PRESSURE)) ? "Ok" : "Fail");
209  if (last_st.onboard_control_sensors_enabled & enum_value(STS::DIFFERENTIAL_PRESSURE))
210  stat.add("differential pressure", (last_st.onboard_control_sensors_health & enum_value(STS::DIFFERENTIAL_PRESSURE)) ? "Ok" : "Fail");
211  if (last_st.onboard_control_sensors_enabled & enum_value(STS::GPS))
212  stat.add("GPS", (last_st.onboard_control_sensors_health & enum_value(STS::GPS)) ? "Ok" : "Fail");
213  if (last_st.onboard_control_sensors_enabled & enum_value(STS::OPTICAL_FLOW))
214  stat.add("optical flow", (last_st.onboard_control_sensors_health & enum_value(STS::OPTICAL_FLOW)) ? "Ok" : "Fail");
215  if (last_st.onboard_control_sensors_enabled & enum_value(STS::VISION_POSITION))
216  stat.add("computer vision position", (last_st.onboard_control_sensors_health & enum_value(STS::VISION_POSITION)) ? "Ok" : "Fail");
217  if (last_st.onboard_control_sensors_enabled & enum_value(STS::LASER_POSITION))
218  stat.add("laser based position", (last_st.onboard_control_sensors_health & enum_value(STS::LASER_POSITION)) ? "Ok" : "Fail");
219  if (last_st.onboard_control_sensors_enabled & enum_value(STS::EXTERNAL_GROUND_TRUTH))
220  stat.add("external ground truth (Vicon or Leica)", (last_st.onboard_control_sensors_health & enum_value(STS::EXTERNAL_GROUND_TRUTH)) ? "Ok" : "Fail");
221  if (last_st.onboard_control_sensors_enabled & enum_value(STS::ANGULAR_RATE_CONTROL))
222  stat.add("3D angular rate control", (last_st.onboard_control_sensors_health & enum_value(STS::ANGULAR_RATE_CONTROL)) ? "Ok" : "Fail");
223  if (last_st.onboard_control_sensors_enabled & enum_value(STS::ATTITUDE_STABILIZATION))
224  stat.add("attitude stabilization", (last_st.onboard_control_sensors_health & enum_value(STS::ATTITUDE_STABILIZATION)) ? "Ok" : "Fail");
225  if (last_st.onboard_control_sensors_enabled & enum_value(STS::YAW_POSITION))
226  stat.add("yaw position", (last_st.onboard_control_sensors_health & enum_value(STS::YAW_POSITION)) ? "Ok" : "Fail");
227  if (last_st.onboard_control_sensors_enabled & enum_value(STS::Z_ALTITUDE_CONTROL))
228  stat.add("z/altitude control", (last_st.onboard_control_sensors_health & enum_value(STS::Z_ALTITUDE_CONTROL)) ? "Ok" : "Fail");
229  if (last_st.onboard_control_sensors_enabled & enum_value(STS::XY_POSITION_CONTROL))
230  stat.add("x/y position control", (last_st.onboard_control_sensors_health & enum_value(STS::XY_POSITION_CONTROL)) ? "Ok" : "Fail");
231  if (last_st.onboard_control_sensors_enabled & enum_value(STS::MOTOR_OUTPUTS))
232  stat.add("motor outputs / control", (last_st.onboard_control_sensors_health & enum_value(STS::MOTOR_OUTPUTS)) ? "Ok" : "Fail");
233  if (last_st.onboard_control_sensors_enabled & enum_value(STS::RC_RECEIVER))
234  stat.add("rc receiver", (last_st.onboard_control_sensors_health & enum_value(STS::RC_RECEIVER)) ? "Ok" : "Fail");
235  if (last_st.onboard_control_sensors_enabled & enum_value(STS::SENSOR_3D_GYRO2))
236  stat.add("2nd 3D gyro", (last_st.onboard_control_sensors_health & enum_value(STS::SENSOR_3D_GYRO2)) ? "Ok" : "Fail");
237  if (last_st.onboard_control_sensors_enabled & enum_value(STS::SENSOR_3D_ACCEL2))
238  stat.add("2nd 3D accelerometer", (last_st.onboard_control_sensors_health & enum_value(STS::SENSOR_3D_ACCEL2)) ? "Ok" : "Fail");
239  if (last_st.onboard_control_sensors_enabled & enum_value(STS::SENSOR_3D_MAG2))
240  stat.add("2nd 3D magnetometer", (last_st.onboard_control_sensors_health & enum_value(STS::SENSOR_3D_MAG2)) ? "Ok" : "Fail");
241  if (last_st.onboard_control_sensors_enabled & enum_value(STS::GEOFENCE))
242  stat.add("geofence", (last_st.onboard_control_sensors_health & enum_value(STS::GEOFENCE)) ? "Ok" : "Fail");
243  if (last_st.onboard_control_sensors_enabled & enum_value(STS::AHRS))
244  stat.add("AHRS subsystem health", (last_st.onboard_control_sensors_health & enum_value(STS::AHRS)) ? "Ok" : "Fail");
245  if (last_st.onboard_control_sensors_enabled & enum_value(STS::TERRAIN))
246  stat.add("Terrain subsystem health", (last_st.onboard_control_sensors_health & enum_value(STS::TERRAIN)) ? "Ok" : "Fail");
247  if (last_st.onboard_control_sensors_enabled & enum_value(STS::REVERSE_MOTOR))
248  stat.add("Motors are reversed", (last_st.onboard_control_sensors_health & enum_value(STS::REVERSE_MOTOR)) ? "Ok" : "Fail");
249  if (last_st.onboard_control_sensors_enabled & enum_value(STS::LOGGING))
250  stat.add("Logging", (last_st.onboard_control_sensors_health & enum_value(STS::LOGGING)) ? "Ok" : "Fail");
251  if (last_st.onboard_control_sensors_enabled & enum_value(STS::BATTERY))
252  stat.add("Battery", (last_st.onboard_control_sensors_health & enum_value(STS::BATTERY)) ? "Ok" : "Fail");
253  if (last_st.onboard_control_sensors_enabled & enum_value(STS::PROXIMITY))
254  stat.add("Proximity", (last_st.onboard_control_sensors_health & enum_value(STS::PROXIMITY)) ? "Ok" : "Fail");
255  if (last_st.onboard_control_sensors_enabled & enum_value(STS::SATCOM))
256  stat.add("Satellite Communication", (last_st.onboard_control_sensors_health & enum_value(STS::SATCOM)) ? "Ok" : "Fail");
257  // [[[end]]] (checksum: 890cfdc6d3b776c38a59b39f80ec7351)
258 
259  stat.addf("CPU Load (%)", "%.1f", last_st.load / 10.0);
260  stat.addf("Drop rate (%)", "%.1f", last_st.drop_rate_comm / 10.0);
261  stat.addf("Errors comm", "%d", last_st.errors_comm);
262  stat.addf("Errors count #1", "%d", last_st.errors_count1);
263  stat.addf("Errors count #2", "%d", last_st.errors_count2);
264  stat.addf("Errors count #3", "%d", last_st.errors_count3);
265  stat.addf("Errors count #4", "%d", last_st.errors_count4);
266  }
267 
268 private:
270  mavlink::common::msg::SYS_STATUS last_st;
271 };
272 
273 
278 {
279 public:
280  BatteryStatusDiag(const std::string &name) :
282  voltage(-1.0),
283  current(0.0),
284  remaining(0.0),
285  min_voltage(6)
286  { }
287 
288  void set_min_voltage(float volt) {
289  std::lock_guard<std::mutex> lock(mutex);
290  min_voltage = volt;
291  }
292 
293  void set(float volt, float curr, float rem) {
294  std::lock_guard<std::mutex> lock(mutex);
295  voltage = volt;
296  current = curr;
297  remaining = rem;
298  }
299 
301  {
302  std::lock_guard<std::mutex> lock(mutex);
303 
304  if (voltage < 0)
305  stat.summary(2, "No data");
306  else if (voltage < min_voltage)
307  stat.summary(1, "Low voltage");
308  else
309  stat.summary(0, "Normal");
310 
311  stat.addf("Voltage", "%.2f", voltage);
312  stat.addf("Current", "%.1f", current);
313  stat.addf("Remaining", "%.1f", remaining * 100);
314  }
315 
316 private:
318  float voltage;
319  float current;
320  float remaining;
321  float min_voltage;
322 };
323 
324 
329 {
330 public:
331  MemInfo(const std::string &name) :
333  freemem(-1),
334  brkval(0)
335  { }
336 
337  void set(uint16_t f, uint16_t b) {
338  freemem = f;
339  brkval = b;
340  }
341 
343  {
344  ssize_t freemem_ = freemem;
345  uint16_t brkval_ = brkval;
346 
347  if (freemem < 0)
348  stat.summary(2, "No data");
349  else if (freemem < 200)
350  stat.summary(1, "Low mem");
351  else
352  stat.summary(0, "Normal");
353 
354  stat.addf("Free memory (B)", "%zd", freemem_);
355  stat.addf("Heap top", "0x%04X", brkval_);
356  }
357 
358 private:
359  std::atomic<ssize_t> freemem;
360  std::atomic<uint16_t> brkval;
361 };
362 
363 
368 {
369 public:
370  HwStatus(const std::string &name) :
372  vcc(-1.0),
373  i2cerr(0),
374  i2cerr_last(0)
375  { }
376 
377  void set(uint16_t v, uint8_t e) {
378  std::lock_guard<std::mutex> lock(mutex);
379  vcc = v / 1000.0;
380  i2cerr = e;
381  }
382 
384  {
385  std::lock_guard<std::mutex> lock(mutex);
386 
387  if (vcc < 0)
388  stat.summary(2, "No data");
389  else if (vcc < 4.5)
390  stat.summary(1, "Low voltage");
391  else if (i2cerr != i2cerr_last) {
392  i2cerr_last = i2cerr;
393  stat.summary(1, "New I2C error");
394  }
395  else
396  stat.summary(0, "Normal");
397 
398  stat.addf("Core voltage", "%f", vcc);
399  stat.addf("I2C errors", "%zu", i2cerr);
400  }
401 
402 private:
404  float vcc;
405  size_t i2cerr;
406  size_t i2cerr_last;
407 };
408 
409 
416 {
417 public:
418  SystemStatusPlugin() : PluginBase(),
419  nh("~"),
420  hb_diag("Heartbeat", 10),
421  mem_diag("APM Memory"),
422  hwst_diag("APM Hardware"),
423  sys_diag("System"),
424  batt_diag("Battery"),
425  version_retries(RETRIES_COUNT),
426  disable_diag(false),
427  has_battery_status(false),
428  battery_voltage(0.0),
429  conn_heartbeat_mav_type(MAV_TYPE::ONBOARD_CONTROLLER)
430  { }
431 
432  void initialize(UAS &uas_)
433  {
434  PluginBase::initialize(uas_);
435 
436  ros::Duration conn_heartbeat;
437 
438  double conn_timeout_d;
439  double conn_heartbeat_d;
440  double min_voltage;
441  std::string conn_heartbeat_mav_type_str;
442 
443  nh.param("conn/timeout", conn_timeout_d, 10.0);
444  nh.param("sys/min_voltage", min_voltage, 10.0);
445  nh.param("sys/disable_diag", disable_diag, false);
446 
447  // heartbeat rate parameter
448  if (nh.getParam("conn/heartbeat_rate", conn_heartbeat_d) && conn_heartbeat_d != 0.0) {
449  conn_heartbeat = ros::Duration(ros::Rate(conn_heartbeat_d));
450  }
451 
452  // heartbeat mav type parameter
453  if (nh.getParam("conn/heartbeat_mav_type", conn_heartbeat_mav_type_str)) {
454  conn_heartbeat_mav_type = utils::mav_type_from_str(conn_heartbeat_mav_type_str);
455  }
456 
457  // heartbeat diag always enabled
458  UAS_DIAG(m_uas).add(hb_diag);
459  if (!disable_diag) {
460  UAS_DIAG(m_uas).add(sys_diag);
461  UAS_DIAG(m_uas).add(batt_diag);
462 
463  batt_diag.set_min_voltage(min_voltage);
464  }
465 
466 
467  // one-shot timeout timer
468  timeout_timer = nh.createTimer(ros::Duration(conn_timeout_d),
469  &SystemStatusPlugin::timeout_cb, this, true);
470  //timeout_timer.start();
471 
472  if (!conn_heartbeat.isZero()) {
473  heartbeat_timer = nh.createTimer(conn_heartbeat,
475  //heartbeat_timer.start();
476  }
477 
478  // version request timer
479  autopilot_version_timer = nh.createTimer(ros::Duration(1.0),
481  autopilot_version_timer.stop();
482 
483  state_pub = nh.advertise<mavros_msgs::State>("state", 10, true);
484  extended_state_pub = nh.advertise<mavros_msgs::ExtendedState>("extended_state", 10);
485  batt_pub = nh.advertise<BatteryMsg>("battery", 10);
486  statustext_pub = nh.advertise<mavros_msgs::StatusText>("statustext/recv", 10);
487  statustext_sub = nh.subscribe("statustext/send", 10, &SystemStatusPlugin::statustext_cb, this);
488  rate_srv = nh.advertiseService("set_stream_rate", &SystemStatusPlugin::set_rate_cb, this);
489  mode_srv = nh.advertiseService("set_mode", &SystemStatusPlugin::set_mode_cb, this);
490  vehicle_info_get_srv = nh.advertiseService("vehicle_info_get", &SystemStatusPlugin::vehicle_info_get_cb, this);
491  message_interval_srv = nh.advertiseService("set_message_interval", &SystemStatusPlugin::set_message_interval_cb, this);
492 
493  // init state topic
494  publish_disconnection();
495  enable_connection_cb();
496  }
497 
499  return {
503  make_handler(&SystemStatusPlugin::handle_meminfo),
508  };
509  }
510 
511 private:
513 
522 
532 
534  static constexpr int RETRIES_COUNT = 6;
539 
540  using M_VehicleInfo = std::unordered_map<uint16_t, mavros_msgs::VehicleInfo>;
542 
543  /* -*- mid-level helpers -*- */
544 
545  // Get vehicle key for the unordered map containing all vehicles
546  inline uint16_t get_vehicle_key(uint8_t sysid,uint8_t compid) {
547  return sysid << 8 | compid;
548  }
549 
550  // Find or create vehicle info
551  inline M_VehicleInfo::iterator find_or_create_vehicle_info(uint8_t sysid, uint8_t compid) {
552  auto key = get_vehicle_key(sysid, compid);
553  M_VehicleInfo::iterator ret = vehicles.find(key);
554 
555  if (ret == vehicles.end()) {
556  // Not found
557  mavros_msgs::VehicleInfo v;
558  v.sysid = sysid;
559  v.compid = compid;
560  v.available_info = 0;
561 
562  auto res = vehicles.emplace(key, v); //-> pair<iterator, bool>
563  ret = res.first;
564  }
565 
566  ROS_ASSERT(ret != vehicles.end());
567  return ret;
568  }
569 
575  void process_statustext_normal(uint8_t severity, std::string &text)
576  {
577  using mavlink::common::MAV_SEVERITY;
578 
579  switch (severity) {
580  // [[[cog:
581  // for l1, l2 in (
582  // (('EMERGENCY', 'ALERT', 'CRITICAL', 'ERROR'), 'ERROR'),
583  // (('WARNING', 'NOTICE'), 'WARN'),
584  // (('INFO', ), 'INFO'),
585  // (('DEBUG', ), 'DEBUG')
586  // ):
587  // for v in l1:
588  // cog.outl("case enum_value(MAV_SEVERITY::%s):" % v)
589  // cog.outl("\tROS_%s_STREAM_NAMED(\"fcu\", \"FCU: \" << text);" % l2)
590  // cog.outl("\tbreak;")
591  // ]]]
592  case enum_value(MAV_SEVERITY::EMERGENCY):
593  case enum_value(MAV_SEVERITY::ALERT):
594  case enum_value(MAV_SEVERITY::CRITICAL):
595  case enum_value(MAV_SEVERITY::ERROR):
596  ROS_ERROR_STREAM_NAMED("fcu", "FCU: " << text);
597  break;
598  case enum_value(MAV_SEVERITY::WARNING):
599  case enum_value(MAV_SEVERITY::NOTICE):
600  ROS_WARN_STREAM_NAMED("fcu", "FCU: " << text);
601  break;
602  case enum_value(MAV_SEVERITY::INFO):
603  ROS_INFO_STREAM_NAMED("fcu", "FCU: " << text);
604  break;
605  case enum_value(MAV_SEVERITY::DEBUG):
606  ROS_DEBUG_STREAM_NAMED("fcu", "FCU: " << text);
607  break;
608  // [[[end]]] (checksum: 315aa363b5ecb4dda66cc8e1e3d3aa48)
609  default:
610  ROS_WARN_STREAM_NAMED("fcu", "FCU: UNK(" << +severity << "): " << text);
611  break;
612  };
613  }
614 
615  static std::string custom_version_to_hex_string(std::array<uint8_t, 8> &array)
616  {
617  // should be little-endian
618  uint64_t b;
619  memcpy(&b, array.data(), sizeof(uint64_t));
620  b = le64toh(b);
621 
622  return utils::format("%016llx", b);
623  }
624 
625  void process_autopilot_version_normal(mavlink::common::msg::AUTOPILOT_VERSION &apv, uint8_t sysid, uint8_t compid)
626  {
627  char prefix[16];
628  std::snprintf(prefix, sizeof(prefix), "VER: %d.%d", sysid, compid);
629 
630  ROS_INFO_NAMED("sys", "%s: Capabilities 0x%016llx", prefix, (long long int)apv.capabilities);
631  ROS_INFO_NAMED("sys", "%s: Flight software: %08x (%s)",
632  prefix,
633  apv.flight_sw_version,
634  custom_version_to_hex_string(apv.flight_custom_version).c_str());
635  ROS_INFO_NAMED("sys", "%s: Middleware software: %08x (%s)",
636  prefix,
637  apv.middleware_sw_version,
638  custom_version_to_hex_string(apv.middleware_custom_version).c_str());
639  ROS_INFO_NAMED("sys", "%s: OS software: %08x (%s)",
640  prefix,
641  apv.os_sw_version,
642  custom_version_to_hex_string(apv.os_custom_version).c_str());
643  ROS_INFO_NAMED("sys", "%s: Board hardware: %08x", prefix, apv.board_version);
644  ROS_INFO_NAMED("sys", "%s: VID/PID: %04x:%04x", prefix, apv.vendor_id, apv.product_id);
645  ROS_INFO_NAMED("sys", "%s: UID: %016llx", prefix, (long long int)apv.uid);
646  }
647 
648  void process_autopilot_version_apm_quirk(mavlink::common::msg::AUTOPILOT_VERSION &apv, uint8_t sysid, uint8_t compid)
649  {
650  char prefix[16];
651  std::snprintf(prefix, sizeof(prefix), "VER: %d.%d", sysid, compid);
652 
653  // Note based on current APM's impl.
654  // APM uses custom version array[8] as a string
655  ROS_INFO_NAMED("sys", "%s: Capabilities 0x%016llx", prefix, (long long int)apv.capabilities);
656  ROS_INFO_NAMED("sys", "%s: Flight software: %08x (%*s)",
657  prefix,
658  apv.flight_sw_version,
659  8, apv.flight_custom_version.data());
660  ROS_INFO_NAMED("sys", "%s: Middleware software: %08x (%*s)",
661  prefix,
662  apv.middleware_sw_version,
663  8, apv.middleware_custom_version.data());
664  ROS_INFO_NAMED("sys", "%s: OS software: %08x (%*s)",
665  prefix,
666  apv.os_sw_version,
667  8, apv.os_custom_version.data());
668  ROS_INFO_NAMED("sys", "%s: Board hardware: %08x", prefix, apv.board_version);
669  ROS_INFO_NAMED("sys", "%s: VID/PID: %04x:%04x", prefix, apv.vendor_id, apv.product_id);
670  ROS_INFO_NAMED("sys", "%s: UID: %016llx", prefix, (long long int)apv.uid);
671  }
672 
674  auto state_msg = boost::make_shared<mavros_msgs::State>();
675  state_msg->header.stamp = ros::Time::now();
676  state_msg->connected = false;
677  state_msg->armed = false;
678  state_msg->guided = false;
679  state_msg->mode = "";
680  state_msg->system_status = enum_value(MAV_STATE::UNINIT);
681 
682  state_pub.publish(state_msg);
683  }
684 
685  /* -*- message handlers -*- */
686 
687  void handle_heartbeat(const mavlink::mavlink_message_t *msg, mavlink::common::msg::HEARTBEAT &hb)
688  {
689  using mavlink::common::MAV_MODE_FLAG;
690 
691  // Store generic info of all heartbeats seen
692  auto it = find_or_create_vehicle_info(msg->sysid, msg->compid);
693 
694  auto vehicle_mode = m_uas->str_mode_v10(hb.base_mode, hb.custom_mode);
695  auto stamp = ros::Time::now();
696 
697  // Update vehicle data
698  it->second.header.stamp = stamp;
699  it->second.available_info |= mavros_msgs::VehicleInfo::HAVE_INFO_HEARTBEAT;
700  it->second.autopilot = hb.autopilot;
701  it->second.type = hb.type;
702  it->second.system_status = hb.system_status;
703  it->second.base_mode = hb.base_mode;
704  it->second.custom_mode = hb.custom_mode;
705  it->second.mode = vehicle_mode;
706 
707  if (!(hb.base_mode & enum_value(MAV_MODE_FLAG::CUSTOM_MODE_ENABLED))) {
708  it->second.mode_id = hb.base_mode;
709  } else {
710  it->second.mode_id = hb.custom_mode;
711  }
712 
713  // Continue from here only if vehicle is my target
714  if (!m_uas->is_my_target(msg->sysid, msg->compid)) {
715  ROS_DEBUG_NAMED("sys", "HEARTBEAT from [%d, %d] dropped.", msg->sysid, msg->compid);
716  return;
717  }
718 
719  // update context && setup connection timeout
720  m_uas->update_heartbeat(hb.type, hb.autopilot, hb.base_mode);
721  m_uas->update_connection_status(true);
722  timeout_timer.stop();
723  timeout_timer.start();
724 
725  // build state message after updating uas
726  auto state_msg = boost::make_shared<mavros_msgs::State>();
727  state_msg->header.stamp = stamp;
728  state_msg->connected = true;
729  state_msg->armed = !!(hb.base_mode & enum_value(MAV_MODE_FLAG::SAFETY_ARMED));
730  state_msg->guided = !!(hb.base_mode & enum_value(MAV_MODE_FLAG::GUIDED_ENABLED));
731  state_msg->mode = vehicle_mode;
732  state_msg->system_status = hb.system_status;
733 
734  state_pub.publish(state_msg);
735  hb_diag.tick(hb.type, hb.autopilot, state_msg->mode, hb.system_status);
736  }
737 
738  void handle_extended_sys_state(const mavlink::mavlink_message_t *msg, mavlink::common::msg::EXTENDED_SYS_STATE &state)
739  {
740  auto state_msg = boost::make_shared<mavros_msgs::ExtendedState>();
741  state_msg->header.stamp = ros::Time::now();
742  state_msg->vtol_state = state.vtol_state;
743  state_msg->landed_state = state.landed_state;
744 
745  extended_state_pub.publish(state_msg);
746  }
747 
748  void handle_sys_status(const mavlink::mavlink_message_t *msg, mavlink::common::msg::SYS_STATUS &stat)
749  {
750  float volt = stat.voltage_battery / 1000.0f; // mV
751  float curr = stat.current_battery / 100.0f; // 10 mA or -1
752  float rem = stat.battery_remaining / 100.0f; // or -1
753 
754  battery_voltage = volt;
755  sys_diag.set(stat);
756  batt_diag.set(volt, curr, rem);
757 
758  if (has_battery_status)
759  return;
760 
761  auto batt_msg = boost::make_shared<BatteryMsg>();
762  batt_msg->header.stamp = ros::Time::now();
763 
764 #ifdef HAVE_SENSOR_MSGS_BATTERYSTATE_MSG
765  batt_msg->voltage = volt;
766  batt_msg->current = -curr;
767  batt_msg->charge = NAN;
768  batt_msg->capacity = NAN;
769  batt_msg->design_capacity = NAN;
770  batt_msg->percentage = rem;
771  batt_msg->power_supply_status = BatteryMsg::POWER_SUPPLY_STATUS_DISCHARGING;
772  batt_msg->power_supply_health = BatteryMsg::POWER_SUPPLY_HEALTH_UNKNOWN;
773  batt_msg->power_supply_technology = BatteryMsg::POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
774  batt_msg->present = true;
775  batt_msg->cell_voltage.clear(); // not necessary. Cell count and Voltage unknown.
776  batt_msg->location = "";
777  batt_msg->serial_number = "";
778 #else // mavros_msgs::BatteryStatus
779  batt_msg->voltage = volt;
780  batt_msg->current = curr;
781  batt_msg->remaining = rem;
782 #endif
783 
784  batt_pub.publish(batt_msg);
785  }
786 
787  void handle_statustext(const mavlink::mavlink_message_t *msg, mavlink::common::msg::STATUSTEXT &textm)
788  {
789  auto text = mavlink::to_string(textm.text);
790  process_statustext_normal(textm.severity, text);
791 
792  auto st_msg = boost::make_shared<mavros_msgs::StatusText>();
793  st_msg->header.stamp = ros::Time::now();
794  st_msg->severity = textm.severity;
795  st_msg->text = text;
796  statustext_pub.publish(st_msg);
797  }
798 
799  void handle_meminfo(const mavlink::mavlink_message_t *msg, mavlink::ardupilotmega::msg::MEMINFO &mem)
800  {
801  mem_diag.set(mem.freemem, mem.brkval);
802  }
803 
804  void handle_hwstatus(const mavlink::mavlink_message_t *msg, mavlink::ardupilotmega::msg::HWSTATUS &hwst)
805  {
806  hwst_diag.set(hwst.Vcc, hwst.I2Cerr);
807  }
808 
809  void handle_autopilot_version(const mavlink::mavlink_message_t *msg, mavlink::common::msg::AUTOPILOT_VERSION &apv)
810  {
811  // we want to store only FCU caps
812  if (m_uas->is_my_target(msg->sysid, msg->compid)) {
813  autopilot_version_timer.stop();
814  m_uas->update_capabilities(true, apv.capabilities);
815  }
816 
817  // but print all version responses
818  if (m_uas->is_ardupilotmega())
819  process_autopilot_version_apm_quirk(apv, msg->sysid, msg->compid);
820  else
821  process_autopilot_version_normal(apv, msg->sysid, msg->compid);
822 
823  // Store generic info of all autopilot seen
824  auto it = find_or_create_vehicle_info(msg->sysid, msg->compid);
825 
826  // Update vehicle data
827  it->second.header.stamp = ros::Time::now();
828  it->second.available_info |= mavros_msgs::VehicleInfo::HAVE_INFO_AUTOPILOT_VERSION;
829  it->second.capabilities = apv.capabilities;
830  it->second.flight_sw_version = apv.flight_sw_version;
831  it->second.middleware_sw_version = apv.middleware_sw_version;
832  it->second.os_sw_version = apv.os_sw_version;
833  it->second.board_version = apv.board_version;
834  it->second.vendor_id = apv.vendor_id;
835  it->second.product_id = apv.product_id;
836  it->second.uid = apv.uid;
837  }
838 
839  void handle_battery_status(const mavlink::mavlink_message_t *msg, mavlink::common::msg::BATTERY_STATUS &bs)
840  {
841  // PX4.
842 #ifdef HAVE_SENSOR_MSGS_BATTERYSTATE_MSG
843  using BT = mavlink::common::MAV_BATTERY_TYPE;
844 
845  has_battery_status = true;
846 
847  auto batt_msg = boost::make_shared<BatteryMsg>();
848  batt_msg->header.stamp = ros::Time::now();
849 
850  batt_msg->voltage = battery_voltage;
851  batt_msg->current = -(bs.current_battery / 100.0f); // 10 mA
852  batt_msg->charge = NAN;
853  batt_msg->capacity = NAN;
854  batt_msg->design_capacity = NAN;
855  batt_msg->percentage = bs.battery_remaining / 100.0f;
856  batt_msg->power_supply_status = BatteryMsg::POWER_SUPPLY_STATUS_DISCHARGING;
857  batt_msg->power_supply_health = BatteryMsg::POWER_SUPPLY_HEALTH_UNKNOWN;
858 
859  switch (bs.type) {
860  // [[[cog:
861  // for f in (
862  // 'LIPO',
863  // 'LIFE',
864  // 'LION',
865  // 'NIMH',
866  // 'UNKNOWN'):
867  // cog.outl("case enum_value(BT::%s):" % f)
868  // if f == 'UNKNOWN':
869  // cog.outl("default:")
870  // cog.outl("\tbatt_msg->power_supply_technology = BatteryMsg::POWER_SUPPLY_TECHNOLOGY_%s;" % f)
871  // cog.outl("\tbreak;")
872  // ]]]
873  case enum_value(BT::LIPO):
874  batt_msg->power_supply_technology = BatteryMsg::POWER_SUPPLY_TECHNOLOGY_LIPO;
875  break;
876  case enum_value(BT::LIFE):
877  batt_msg->power_supply_technology = BatteryMsg::POWER_SUPPLY_TECHNOLOGY_LIFE;
878  break;
879  case enum_value(BT::LION):
880  batt_msg->power_supply_technology = BatteryMsg::POWER_SUPPLY_TECHNOLOGY_LION;
881  break;
882  case enum_value(BT::NIMH):
883  batt_msg->power_supply_technology = BatteryMsg::POWER_SUPPLY_TECHNOLOGY_NIMH;
884  break;
885  case enum_value(BT::UNKNOWN):
886  default:
887  batt_msg->power_supply_technology = BatteryMsg::POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
888  break;
889  // [[[end]]] (checksum: 2bf14a81b3027f14ba1dd9b4c086a41d)
890  }
891 
892  batt_msg->present = true;
893 
894  batt_msg->cell_voltage.clear();
895  batt_msg->cell_voltage.reserve(bs.voltages.size());
896  for (auto v : bs.voltages) {
897  if (v == UINT16_MAX)
898  break;
899 
900  batt_msg->cell_voltage.push_back(v / 1000.0f); // 1 mV
901  }
902 
903  batt_msg->location = utils::format("id%u", bs.id);
904  batt_msg->serial_number = "";
905 
906  batt_pub.publish(batt_msg);
907 #endif
908  }
909 
910  /* -*- timer callbacks -*- */
911 
912  void timeout_cb(const ros::TimerEvent &event)
913  {
914  m_uas->update_connection_status(false);
915  }
916 
917  void heartbeat_cb(const ros::TimerEvent &event)
918  {
919  using mavlink::common::MAV_MODE;
920 
921  mavlink::common::msg::HEARTBEAT hb {};
922 
923  hb.type = enum_value(conn_heartbeat_mav_type);
924  hb.autopilot = enum_value(MAV_AUTOPILOT::INVALID);
925  hb.base_mode = enum_value(MAV_MODE::MANUAL_ARMED);
926  hb.custom_mode = 0;
927  hb.system_status = enum_value(MAV_STATE::ACTIVE);
928 
929  UAS_FCU(m_uas)->send_message_ignore_drop(hb);
930  }
931 
933  {
934  using mavlink::common::MAV_CMD;
935 
936  bool ret = false;
937 
938  // Request from all first 3 times, then fallback to unicast
939  bool do_broadcast = version_retries > RETRIES_COUNT / 2;
940 
941  try {
942  auto client = nh.serviceClient<mavros_msgs::CommandLong>("cmd/command");
943 
944  mavros_msgs::CommandLong cmd{};
945 
946  cmd.request.broadcast = do_broadcast;
947  cmd.request.command = enum_value(MAV_CMD::REQUEST_AUTOPILOT_CAPABILITIES);
948  cmd.request.confirmation = false;
949  cmd.request.param1 = 1.0;
950 
951  ROS_DEBUG_NAMED("sys", "VER: Sending %s request.",
952  (do_broadcast) ? "broadcast" : "unicast");
953  ret = client.call(cmd);
954  }
955  catch (ros::InvalidNameException &ex) {
956  ROS_ERROR_NAMED("sys", "VER: %s", ex.what());
957  }
958 
959  ROS_ERROR_COND_NAMED(!ret, "sys", "VER: command plugin service call failed!");
960 
961  if (version_retries > 0) {
962  version_retries--;
963  ROS_WARN_COND_NAMED(version_retries != RETRIES_COUNT - 1, "sys",
964  "VER: %s request timeout, retries left %d",
965  (do_broadcast) ? "broadcast" : "unicast",
966  version_retries);
967  }
968  else {
969  m_uas->update_capabilities(false);
970  autopilot_version_timer.stop();
971  ROS_WARN_NAMED("sys", "VER: your FCU don't support AUTOPILOT_VERSION, "
972  "switched to default capabilities");
973  }
974  }
975 
976  void connection_cb(bool connected) override
977  {
978  has_battery_status = false;
979 
980  // if connection changes, start delayed version request
981  version_retries = RETRIES_COUNT;
982  if (connected)
983  autopilot_version_timer.start();
984  else
985  autopilot_version_timer.stop();
986 
987  // add/remove APM diag tasks
988  if (connected && disable_diag && m_uas->is_ardupilotmega()) {
989  UAS_DIAG(m_uas).add(mem_diag);
990  UAS_DIAG(m_uas).add(hwst_diag);
991  }
992  else {
993  UAS_DIAG(m_uas).removeByName(mem_diag.getName());
994  UAS_DIAG(m_uas).removeByName(hwst_diag.getName());
995  }
996 
997  if (!connected) {
998  // publish connection change
999  publish_disconnection();
1000 
1001  // Clear known vehicles
1002  vehicles.clear();
1003  }
1004  }
1005 
1006  /* -*- subscription callbacks -*- */
1007 
1009  mavlink::common::msg::STATUSTEXT statustext {};
1010  statustext.severity = req->severity;
1011 
1012  // Limit the length of the string by null-terminating at the 50-th character
1013  ROS_WARN_COND_NAMED(req->text.length() >= statustext.text.size(), "sys",
1014  "Status text too long: truncating...");
1015  mavlink::set_string_z(statustext.text, req->text);
1016 
1017  UAS_FCU(m_uas)->send_message_ignore_drop(statustext);
1018  }
1019 
1020  /* -*- ros callbacks -*- */
1021 
1022  bool set_rate_cb(mavros_msgs::StreamRate::Request &req,
1023  mavros_msgs::StreamRate::Response &res)
1024  {
1025  mavlink::common::msg::REQUEST_DATA_STREAM rq;
1026 
1027  rq.target_system = m_uas->get_tgt_system();
1028  rq.target_component = m_uas->get_tgt_component();
1029  rq.req_stream_id = req.stream_id;
1030  rq.req_message_rate = req.message_rate;
1031  rq.start_stop = (req.on_off) ? 1 : 0;
1032 
1033  UAS_FCU(m_uas)->send_message_ignore_drop(rq);
1034  return true;
1035  }
1036 
1037  bool set_mode_cb(mavros_msgs::SetMode::Request &req,
1038  mavros_msgs::SetMode::Response &res)
1039  {
1040  using mavlink::common::MAV_MODE_FLAG;
1041 
1042  uint8_t base_mode = req.base_mode;
1043  uint32_t custom_mode = 0;
1044 
1045  if (req.custom_mode != "") {
1046  if (!m_uas->cmode_from_str(req.custom_mode, custom_mode)) {
1047  res.mode_sent = false;
1048  return true;
1049  }
1050 
1056  base_mode |= (m_uas->get_armed()) ? enum_value(MAV_MODE_FLAG::SAFETY_ARMED) : 0;
1057  base_mode |= (m_uas->get_hil_state()) ? enum_value(MAV_MODE_FLAG::HIL_ENABLED) : 0;
1058  base_mode |= enum_value(MAV_MODE_FLAG::CUSTOM_MODE_ENABLED);
1059  }
1060 
1061  mavlink::common::msg::SET_MODE sm;
1062  sm.target_system = m_uas->get_tgt_system();
1063  sm.base_mode = base_mode;
1064  sm.custom_mode = custom_mode;
1065 
1066  UAS_FCU(m_uas)->send_message_ignore_drop(sm);
1067  res.mode_sent = true;
1068  return true;
1069  }
1070 
1071  bool vehicle_info_get_cb(mavros_msgs::VehicleInfoGet::Request &req,
1072  mavros_msgs::VehicleInfoGet::Response &res)
1073  {
1074  if (req.get_all) {
1075  // Send all vehicles
1076  for (const auto &got : vehicles) {
1077  res.vehicles.emplace_back(got.second);
1078  }
1079 
1080  res.success = true;
1081  return res.success;
1082  }
1083 
1084  uint8_t req_sysid = req.sysid;
1085  uint8_t req_compid = req.compid;
1086 
1087  if (req.sysid == 0 && req.compid == 0) {
1088  // use target
1089  req_sysid = m_uas->get_tgt_system();
1090  req_compid = m_uas->get_tgt_component();
1091  }
1092 
1093  uint16_t key = get_vehicle_key(req_sysid, req_compid);
1094  auto it = vehicles.find(key);
1095 
1096  if (it == vehicles.end()) {
1097  // Vehicle not found
1098  res.success = false;
1099  return res.success;
1100  }
1101 
1102  res.vehicles.emplace_back(it->second);
1103  res.success = true;
1104  return res.success;
1105  }
1106 
1107  bool set_message_interval_cb(mavros_msgs::MessageInterval::Request &req,
1108  mavros_msgs::MessageInterval::Response &res)
1109  {
1110  using mavlink::common::MAV_CMD;
1111 
1112  try {
1113  auto client = nh.serviceClient<mavros_msgs::CommandLong>("cmd/command");
1114 
1115  // calculate interval
1116  float interval_us;
1117  if (req.message_rate < 0) {
1118  interval_us = -1.0f;
1119  } else if (req.message_rate == 0) {
1120  interval_us = 0.0f;
1121  } else {
1122  interval_us = 1000000.0f / req.message_rate;
1123  }
1124 
1125  mavros_msgs::CommandLong cmd{};
1126 
1127  cmd.request.broadcast = false;
1128  cmd.request.command = enum_value(MAV_CMD::SET_MESSAGE_INTERVAL);
1129  cmd.request.confirmation = false;
1130  cmd.request.param1 = req.message_id;
1131  cmd.request.param2 = interval_us;
1132 
1133  ROS_DEBUG_NAMED("sys", "SetMessageInterval: Request msgid %u at %f hz",
1134  req.message_id, req.message_rate);
1135  res.success = client.call(cmd);
1136  }
1137  catch (ros::InvalidNameException &ex) {
1138  ROS_ERROR_NAMED("sys", "SetMessageInterval: %s", ex.what());
1139  }
1140 
1141  ROS_ERROR_COND_NAMED(!res.success, "sys", "SetMessageInterval: command plugin service call failed!");
1142 
1143  return res.success;
1144  }
1145 };
1146 } // namespace std_plugins
1147 } // namespace mavros
1148 
MemInfo(const std::string &name)
Definition: sys_status.cpp:331
MAVROS Plugin base class.
Definition: mavros_plugin.h:37
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
#define ROS_ERROR_COND_NAMED(cond, name,...)
#define ROS_WARN_COND_NAMED(cond, name,...)
std::shared_ptr< MAVConnInterface const > ConstPtr
bool set_mode_cb(mavros_msgs::SetMode::Request &req, mavros_msgs::SetMode::Response &res)
#define ROS_INFO_NAMED(name,...)
void run(diagnostic_updater::DiagnosticStatusWrapper &stat)
Definition: sys_status.cpp:163
std::atomic< uint16_t > brkval
Definition: sys_status.cpp:360
#define ROS_DEBUG_STREAM_NAMED(name, args)
std::string format(const std::string &fmt, Args...args)
void heartbeat_cb(const ros::TimerEvent &event)
Definition: sys_status.cpp:917
std::vector< ros::Time > times_
Definition: sys_status.cpp:130
mavros_msgs::BatteryStatus BatteryMsg
Definition: sys_status.cpp:35
void publish(const boost::shared_ptr< M > &message) const
bool vehicle_info_get_cb(mavros_msgs::VehicleInfoGet::Request &req, mavros_msgs::VehicleInfoGet::Response &res)
#define ROS_ERROR_STREAM_NAMED(name, args)
#define ROS_WARN_NAMED(name,...)
System status diagnostic updater.
Definition: sys_status.cpp:149
void summary(unsigned char lvl, const std::string s)
MAVROS Plugin base.
string cmd
std::unordered_map< uint16_t, mavros_msgs::VehicleInfo > M_VehicleInfo
Definition: sys_status.cpp:540
void statustext_cb(const mavros_msgs::StatusText::ConstPtr &req)
void process_autopilot_version_apm_quirk(mavlink::common::msg::AUTOPILOT_VERSION &apv, uint8_t sysid, uint8_t compid)
Definition: sys_status.cpp:648
void handle_autopilot_version(const mavlink::mavlink_message_t *msg, mavlink::common::msg::AUTOPILOT_VERSION &apv)
Definition: sys_status.cpp:809
void handle_sys_status(const mavlink::mavlink_message_t *msg, mavlink::common::msg::SYS_STATUS &stat)
Definition: sys_status.cpp:748
void tick(uint8_t type_, uint8_t autopilot_, std::string &mode_, uint8_t system_status_)
Definition: sys_status.cpp:82
void stop()
void set(float volt, float curr, float rem)
Definition: sys_status.cpp:293
void start()
void handle_battery_status(const mavlink::mavlink_message_t *msg, mavlink::common::msg::BATTERY_STATUS &bs)
Definition: sys_status.cpp:839
#define UAS_DIAG(uasobjptr)
helper accessor to diagnostic updater
Definition: mavros_uas.h:47
#define ROS_INFO_STREAM_NAMED(name, args)
void process_autopilot_version_normal(mavlink::common::msg::AUTOPILOT_VERSION &apv, uint8_t sysid, uint8_t compid)
Definition: sys_status.cpp:625
void timeout_cb(const ros::TimerEvent &event)
Definition: sys_status.cpp:912
void addf(const std::string &key, const char *format,...)
Memory usage diag (APM-only)
Definition: sys_status.cpp:328
void run(diagnostic_updater::DiagnosticStatusWrapper &stat)
Definition: sys_status.cpp:300
mavlink::common::msg::SYS_STATUS last_st
Definition: sys_status.cpp:270
bool set_message_interval_cb(mavros_msgs::MessageInterval::Request &req, mavros_msgs::MessageInterval::Response &res)
bool set_rate_cb(mavros_msgs::StreamRate::Request &req, mavros_msgs::StreamRate::Response &res)
uint16_t get_vehicle_key(uint8_t sysid, uint8_t compid)
Definition: sys_status.cpp:546
#define ROS_DEBUG_NAMED(name,...)
void handle_extended_sys_state(const mavlink::mavlink_message_t *msg, mavlink::common::msg::EXTENDED_SYS_STATE &state)
Definition: sys_status.cpp:738
void run(diagnostic_updater::DiagnosticStatusWrapper &stat)
Definition: sys_status.cpp:342
void handle_hwstatus(const mavlink::mavlink_message_t *msg, mavlink::ardupilotmega::msg::HWSTATUS &hwst)
Definition: sys_status.cpp:804
UAS for plugins.
Definition: mavros_uas.h:66
void handle_statustext(const mavlink::mavlink_message_t *msg, mavlink::common::msg::STATUSTEXT &textm)
Definition: sys_status.cpp:787
mavlink::common::MAV_TYPE mav_type_from_str(const std::string &mav_type)
Retreive MAV_TYPE from name.
void handle_meminfo(const mavlink::mavlink_message_t *msg, mavlink::ardupilotmega::msg::MEMINFO &mem)
Definition: sys_status.cpp:799
#define UAS_FCU(uasobjptr)
helper accessor to FCU link interface
Definition: mavros_uas.h:41
std::atomic< ssize_t > freemem
Definition: sys_status.cpp:359
HeartbeatStatus(const std::string &name, size_t win_size)
Definition: sys_status.cpp:53
std::string to_string(timesync_mode e)
SystemStatusDiag(const std::string &name)
Definition: sys_status.cpp:152
HwStatus(const std::string &name)
Definition: sys_status.cpp:370
Battery diagnostic updater.
Definition: sys_status.cpp:277
void initialize(UAS &uas_)
Plugin initializer.
Definition: sys_status.cpp:432
void run(diagnostic_updater::DiagnosticStatusWrapper &stat)
Definition: sys_status.cpp:94
void handle_heartbeat(const mavlink::mavlink_message_t *msg, mavlink::common::msg::HEARTBEAT &hb)
Definition: sys_status.cpp:687
void autopilot_version_cb(const ros::TimerEvent &event)
Definition: sys_status.cpp:932
const std::string & getName()
DiagnosticTask(const std::string name)
Subscriptions get_subscriptions()
Return vector of MAVLink message subscriptions (handlers)
Definition: sys_status.cpp:498
BatteryStatusDiag(const std::string &name)
Definition: sys_status.cpp:280
std::vector< HandlerInfo > Subscriptions
Subscriptions vector.
Definition: mavros_plugin.h:48
#define ROS_ERROR_NAMED(name,...)
void connection_cb(bool connected) override
Definition: sys_status.cpp:976
static Time now()
M_VehicleInfo::iterator find_or_create_vehicle_info(uint8_t sysid, uint8_t compid)
Definition: sys_status.cpp:551
static std::string custom_version_to_hex_string(std::array< uint8_t, 8 > &array)
Definition: sys_status.cpp:615
void add(const std::string &key, const T &val)
res
#define ROS_ASSERT(cond)
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
void set(uint16_t v, uint8_t e)
Definition: sys_status.cpp:377
void set(uint16_t f, uint16_t b)
Definition: sys_status.cpp:337
void run(diagnostic_updater::DiagnosticStatusWrapper &stat)
Definition: sys_status.cpp:383
Hardware status (APM-only)
Definition: sys_status.cpp:367
void set(mavlink::common::msg::SYS_STATUS &st)
Definition: sys_status.cpp:157
void process_statustext_normal(uint8_t severity, std::string &text)
Definition: sys_status.cpp:575
constexpr std::underlying_type< _T >::type enum_value(_T e)
Definition: utils.h:55
std::recursive_mutex mutex
#define ROS_WARN_STREAM_NAMED(name, args)


mavros
Author(s): Vladimir Ermakov
autogenerated on Mon Jul 8 2019 03:20:11