galactic/include/diagnostic_updater/diagnostic_updater.hpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2008, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of the Willow Garage nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 #ifndef DIAGNOSTIC_UPDATER__DIAGNOSTIC_UPDATER_HPP_
36 #define DIAGNOSTIC_UPDATER__DIAGNOSTIC_UPDATER_HPP_
37 
38 #include <functional> // for bind()
39 #include <memory>
40 #include <stdexcept>
41 #include <string>
42 #include <vector>
43 
44 #include "builtin_interfaces/msg/time.hpp"
45 
46 #include "diagnostic_msgs/msg/diagnostic_array.hpp"
47 #include "diagnostic_msgs/msg/diagnostic_status.hpp"
48 
49 #include "diagnostic_updater/diagnostic_status_wrapper.hpp"
50 
51 #include "rcl/time.h"
52 
53 #include "rclcpp/create_timer.hpp"
54 #include "rclcpp/rclcpp.hpp"
55 
56 namespace diagnostic_updater
57 {
58 
59 typedef std::function<void (DiagnosticStatusWrapper &)> TaskFunction;
60 typedef std::function<void (diagnostic_msgs::msg::DiagnosticStatus &)>
62 
72 class DiagnosticTask
73 {
74 public:
78  explicit DiagnosticTask(const std::string name)
79  : name_(name) {}
80 
84  const std::string & getName() {return name_;}
85 
89  virtual void run(diagnostic_updater::DiagnosticStatusWrapper & stat) = 0;
90 
94  virtual ~DiagnosticTask() {}
95 
96 private:
97  const std::string name_;
98 };
99 
111 template<class T>
112 class GenericFunctionDiagnosticTask : public DiagnosticTask
113 {
114 public:
124  const std::string & name,
125  std::function<void(T &)> fn)
126  : DiagnosticTask(name), fn_(fn) {}
127 
128  virtual void run(DiagnosticStatusWrapper & stat) {fn_(stat);}
129 
130 private:
131  const std::string name_;
132  const TaskFunction fn_;
133 };
134 
135 typedef GenericFunctionDiagnosticTask<diagnostic_msgs::msg::DiagnosticStatus>
137 typedef GenericFunctionDiagnosticTask<DiagnosticStatusWrapper>
139 
152 class CompositeDiagnosticTask : public DiagnosticTask
153 {
154 public:
158  explicit CompositeDiagnosticTask(const std::string name)
159  : DiagnosticTask(name) {}
160 
164  virtual void run(DiagnosticStatusWrapper & stat)
165  {
166  DiagnosticStatusWrapper combined_summary;
167  DiagnosticStatusWrapper original_summary;
168 
169  original_summary.summary(stat);
170 
171  for (std::vector<DiagnosticTask *>::iterator i = tasks_.begin();
172  i != tasks_.end(); i++)
173  {
174  // Put the summary that was passed in.
175  stat.summary(original_summary);
176  // Let the next task add entries and put its summary.
177  (*i)->run(stat);
178  // Merge the new summary into the combined summary.
179  combined_summary.mergeSummary(stat);
180  }
181 
182  // Copy the combined summary into the output.
183  stat.summary(combined_summary);
184  }
185 
192  void addTask(DiagnosticTask * t) {tasks_.push_back(t);}
193 
194 private:
195  std::vector<DiagnosticTask *> tasks_;
196 };
197 
206 class DiagnosticTaskVector
207 {
208 protected:
213  class DiagnosticTaskInternal
214  {
215 public:
216  DiagnosticTaskInternal(const std::string name, TaskFunction f)
217  : name_(name), fn_(f) {}
218 
220  {
221  stat.name = name_;
222  fn_(stat);
223  }
224 
225  const std::string & getName() const {return name_;}
226 
227 private:
228  std::string name_;
230  };
231 
232  std::mutex lock_;
233 
237  const std::vector<DiagnosticTaskInternal> & getTasks() {return tasks_;}
238 
239 public:
240  virtual ~DiagnosticTaskVector() {}
241 
253  void add(const std::string & name, TaskFunction f)
254  {
255  DiagnosticTaskInternal int_task(name, f);
256  addInternal(int_task);
257  }
258 
266  void add(DiagnosticTask & task)
267  {
268  TaskFunction f = std::bind(&DiagnosticTask::run, &task, std::placeholders::_1);
269  add(task.getName(), f);
270  }
271 
285  template<class T>
286  void add(
287  const std::string name, T * c,
289  {
290  DiagnosticTaskInternal int_task(name, std::bind(f, c, std::placeholders::_1));
291  addInternal(int_task);
292  }
293 
304  bool removeByName(const std::string name)
305  {
306  std::unique_lock<std::mutex> lock(lock_);
307  for (std::vector<DiagnosticTaskInternal>::iterator iter = tasks_.begin();
308  iter != tasks_.end(); iter++)
309  {
310  if (iter->getName() == name) {
311  tasks_.erase(iter);
312  return true;
313  }
314 
316  }
317  return false;
318  }
319 
320 private:
326  virtual void addedTaskCallback(DiagnosticTaskInternal &) {}
327  std::vector<DiagnosticTaskInternal> tasks_;
328 
329 protected:
333  void addInternal(DiagnosticTaskInternal & task)
334  {
335  std::unique_lock<std::mutex> lock(lock_);
336  tasks_.push_back(task);
337  addedTaskCallback(task);
338  }
339 };
340 
352 class Updater : public DiagnosticTaskVector
353 {
354 public:
355  bool verbose_;
356 
365  template<class NodeT>
366  explicit Updater(NodeT node, double period = 1.0)
367  : Updater(
368  node->get_node_base_interface(),
369  node->get_node_logging_interface(),
370  node->get_node_parameters_interface(),
371  node->get_node_timers_interface(),
372  node->get_node_topics_interface(),
373  period)
374  {}
375 
376  Updater(
377  std::shared_ptr<rclcpp::node_interfaces::NodeBaseInterface> base_interface,
378  std::shared_ptr<rclcpp::node_interfaces::NodeLoggingInterface> logging_interface,
379  std::shared_ptr<rclcpp::node_interfaces::NodeParametersInterface> parameters_interface,
380  std::shared_ptr<rclcpp::node_interfaces::NodeTimersInterface> timers_interface,
381  std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface> topics_interface,
382  double period = 1.0)
383  : verbose_(false),
384  base_interface_(base_interface),
385  timers_interface_(timers_interface),
386  clock_(std::make_shared<rclcpp::Clock>(RCL_ROS_TIME)),
387  period_(rclcpp::Duration::from_nanoseconds(period * 1e9)),
388  publisher_(
389  rclcpp::create_publisher<diagnostic_msgs::msg::DiagnosticArray>(
390  topics_interface, "/diagnostics", 1)),
391  logger_(logging_interface->get_logger()),
392  node_name_(base_interface->get_name()),
393  warn_nohwid_done_(false)
394  {
395  period = parameters_interface->declare_parameter(
396  "diagnostic_updater.period", rclcpp::ParameterValue(period)).get<double>();
397  period_ = rclcpp::Duration::from_nanoseconds(period * 1e9);
398 
399  reset_timer();
400  }
401 
405  auto getPeriod() const {return period_;}
406 
410  void setPeriod(rclcpp::Duration period)
411  {
412  period_ = period;
413  reset_timer();
414  }
415 
419  void setPeriod(double period)
420  {
421  setPeriod(rclcpp::Duration::from_nanoseconds(period * 1e9));
422  }
423 
427  void force_update()
428  {
429  update();
430  }
431 
442  void broadcast(int lvl, const std::string msg)
443  {
444  std::vector<diagnostic_msgs::msg::DiagnosticStatus> status_vec;
445 
446  const std::vector<DiagnosticTaskInternal> & tasks = getTasks();
447  for (std::vector<DiagnosticTaskInternal>::const_iterator iter =
448  tasks.begin();
449  iter != tasks.end(); iter++)
450  {
452 
453  status.name = iter->getName();
454  status.summary(lvl, msg);
455 
456  status_vec.push_back(status);
457  }
458 
459  publish(status_vec);
460  }
461 
462  void setHardwareIDf(const char * format, ...)
463  {
464  va_list va;
465  const int kBufferSize = 1000;
466  char buff[kBufferSize]; // @todo This could be done more elegantly.
467  va_start(va, format);
468  if (vsnprintf(buff, kBufferSize, format, va) >= kBufferSize) {
469  RCLCPP_DEBUG(logger_, "Really long string in diagnostic_updater::setHardwareIDf.");
470  }
471  hwid_ = std::string(buff);
472  va_end(va);
473  }
474 
475  void setHardwareID(const std::string & hwid) {hwid_ = hwid;}
476 
477 private:
478  void reset_timer()
479  {
480  update_timer_ = rclcpp::create_timer(
481  base_interface_,
482  timers_interface_,
483  clock_,
484  period_,
485  std::bind(&Updater::update, this));
486  }
487 
492  void update()
493  {
494  if (rclcpp::ok()) {
495  bool warn_nohwid = hwid_.empty();
496 
497  std::vector<diagnostic_msgs::msg::DiagnosticStatus> status_vec;
498 
499  std::unique_lock<std::mutex> lock(
500  lock_); // Make sure no adds happen while we are processing here.
501  const std::vector<DiagnosticTaskInternal> & tasks = getTasks();
502  for (std::vector<DiagnosticTaskInternal>::const_iterator iter =
503  tasks.begin();
504  iter != tasks.end(); iter++)
505  {
507 
508  status.name = iter->getName();
509  status.level = 2;
510  status.message = "No message was set";
511  status.hardware_id = hwid_;
512 
513  iter->run(status);
514 
515  status_vec.push_back(status);
516 
517  if (status.level) {
518  warn_nohwid = false;
519  }
520 
521  if (verbose_ && status.level) {
522  RCLCPP_WARN(
523  logger_, "Non-zero diagnostic status. Name: '%s', status %i: '%s'",
524  status.name.c_str(), status.level, status.message.c_str());
525  }
526  }
527 
528  if (warn_nohwid && !warn_nohwid_done_) {
529  std::string error_msg = "diagnostic_updater: No HW_ID was set.";
530  error_msg += " This is probably a bug. Please report it.";
531  error_msg += " For devices that do not have a HW_ID, set this value to 'none'.";
532  error_msg += " This warning only occurs once all diagnostics are OK.";
533  error_msg += " It is okay to wait until the device is open before calling setHardwareID.";
534  RCLCPP_WARN(logger_, "%s", error_msg.c_str());
535  warn_nohwid_done_ = true;
536  }
537 
538  publish(status_vec);
539  }
540  }
541 
546  // TODO(Karsten1987) Follow up PR for eloquent
547  // void update_diagnostic_period()
548  // {
549  // // rcl_duration_value_t old_period = period_;
550  // // next_time_ = next_time_ +
551  // // rclcpp::Duration(period_ - old_period); // Update next_time_
552  // }
553 
558  {
559  std::vector<diagnostic_msgs::msg::DiagnosticStatus> status_vec;
560  status_vec.push_back(stat);
561  publish(status_vec);
562  }
563 
567  void publish(std::vector<diagnostic_msgs::msg::DiagnosticStatus> & status_vec)
568  {
569  for (std::vector<diagnostic_msgs::msg::DiagnosticStatus>::iterator iter =
570  status_vec.begin();
571  iter != status_vec.end(); iter++)
572  {
573  iter->name = node_name_ + std::string(": ") + iter->name;
574  }
576  msg.status = status_vec;
577  msg.header.stamp = rclcpp::Clock().now();
578  publisher_->publish(msg);
579  }
580 
585  virtual void addedTaskCallback(DiagnosticTaskInternal & task)
586  {
587  DiagnosticStatusWrapper stat;
588  stat.name = task.getName();
589  stat.summary(0, "Node starting up");
590  publish(stat);
591  }
592 
593  rclcpp::node_interfaces::NodeBaseInterface::SharedPtr base_interface_;
594  rclcpp::node_interfaces::NodeTimersInterface::SharedPtr timers_interface_;
595  rclcpp::Clock::SharedPtr clock_;
597  rclcpp::TimerBase::SharedPtr update_timer_;
598  rclcpp::Publisher<diagnostic_msgs::msg::DiagnosticArray>::SharedPtr publisher_;
599  rclcpp::Logger logger_;
600 
601  std::string hwid_;
602  std::string node_name_;
603  bool warn_nohwid_done_;
604 };
605 } // namespace diagnostic_updater
606 
607 #endif // DIAGNOSTIC_UPDATER__DIAGNOSTIC_UPDATER_HPP_
diagnostic_updater::CompositeDiagnosticTask::addTask
void addTask(DiagnosticTask *t)
diagnostic_updater::Updater::addedTaskCallback
virtual void addedTaskCallback(DiagnosticTaskInternal &task)
diagnostic_updater::DiagnosticTask::name_
const std::string name_
Definition: eloquent/include/diagnostic_updater/diagnostic_updater.hpp:98
diagnostic_updater::CompositeDiagnosticTask::tasks_
std::vector< DiagnosticTask * > tasks_
Definition: eloquent/include/diagnostic_updater/diagnostic_updater.hpp:196
diagnostic_updater::DiagnosticTaskVector::DiagnosticTaskInternal::name_
std::string name_
Definition: eloquent/include/diagnostic_updater/diagnostic_updater.hpp:229
msg
msg
diagnostic_updater::DiagnosticTaskVector::lock_
boost::mutex lock_
Definition: foxy/include/diagnostic_updater/diagnostic_updater.hpp:233
diagnostic_updater::Updater::setHardwareIDf
void setHardwareIDf(const char *format,...)
diagnostic_updater::Updater::force_update
void force_update()
diagnostic_updater::DiagnosticTask::DiagnosticTask
DiagnosticTask(const std::string name)
diagnostic_updater::UnwrappedTaskFunction
boost::function< void(diagnostic_msgs::DiagnosticStatus &)> UnwrappedTaskFunction
Definition: foxy/include/diagnostic_updater/diagnostic_updater.hpp:62
diagnostic_updater::DiagnosticTaskVector::DiagnosticTaskInternal::getName
const std::string & getName() const
diagnostic_updater::Updater::node_name_
std::string node_name_
Definition: eloquent/include/diagnostic_updater/diagnostic_updater.hpp:612
diagnostic_updater::GenericFunctionDiagnosticTask::fn_
const TaskFunction fn_
Definition: eloquent/include/diagnostic_updater/diagnostic_updater.hpp:133
diagnostic_msgs::DiagnosticStatus
::diagnostic_msgs::DiagnosticStatus_< std::allocator< void > > DiagnosticStatus
Definition: DiagnosticStatus.h:73
diagnostic_updater::DiagnosticTask::~DiagnosticTask
virtual ~DiagnosticTask()
ros::Publisher::publish
void publish(const boost::shared_ptr< M > &message) const
diagnostic_updater::Updater::broadcast
void broadcast(int lvl, const std::string msg)
f
f
diagnostic_updater::GenericFunctionDiagnosticTask::GenericFunctionDiagnosticTask
GenericFunctionDiagnosticTask(const std::string &name, boost::function< void(T &)> fn)
std_msgs::Duration
::std_msgs::Duration_< std::allocator< void > > Duration
Definition: Duration.h:48
diagnostic_updater::Updater::verbose_
bool verbose_
Definition: eloquent/include/diagnostic_updater/diagnostic_updater.hpp:356
diagnostic_updater::UnwrappedFunctionDiagnosticTask
GenericFunctionDiagnosticTask< diagnostic_msgs::DiagnosticStatus > UnwrappedFunctionDiagnosticTask
Definition: foxy/include/diagnostic_updater/diagnostic_updater.hpp:137
api.setup.name
name
Definition: python/api/setup.py:12
diagnostic_updater::DiagnosticTask::run
virtual void run(diagnostic_updater::DiagnosticStatusWrapper &stat)=0
polar_to_cartesian_pointcloud_ros1.node
node
Definition: polar_to_cartesian_pointcloud_ros1.py:81
diagnostic_updater::Updater::Updater
Updater(ros::NodeHandle h=ros::NodeHandle(), ros::NodeHandle ph=ros::NodeHandle("~"), std::string node_name=ros::this_node::getName())
diagnostic_updater
Author: Blaise Gassend.
diagnostic_updater::Updater::publisher_
ros::Publisher publisher_
Definition: diagnostic_updater.h:583
diagnostic_updater::Updater::period_
double period_
Definition: diagnostic_updater.h:587
diagnostic_updater::Updater::hwid_
std::string hwid_
Definition: eloquent/include/diagnostic_updater/diagnostic_updater.hpp:611
diagnostic_updater::DiagnosticTaskVector::DiagnosticTaskInternal::fn_
TaskFunction fn_
Definition: eloquent/include/diagnostic_updater/diagnostic_updater.hpp:230
diagnostic_updater::TaskFunction
boost::function< void(DiagnosticStatusWrapper &)> TaskFunction
Definition: foxy/include/diagnostic_updater/diagnostic_updater.hpp:60
diagnostic_updater::Updater::setHardwareID
void setHardwareID(const std::string &hwid)
diagnostic_updater::DiagnosticTaskVector::addedTaskCallback
virtual void addedTaskCallback(DiagnosticTaskInternal &)
diagnostic_updater::DiagnosticTaskVector::DiagnosticTaskInternal::DiagnosticTaskInternal
DiagnosticTaskInternal(const std::string name, TaskFunction f)
diagnostic_updater::Updater::update
void update()
diagnostic_updater::FunctionDiagnosticTask
GenericFunctionDiagnosticTask< DiagnosticStatusWrapper > FunctionDiagnosticTask
Definition: foxy/include/diagnostic_updater/diagnostic_updater.hpp:139
diagnostic_updater::Updater::warn_nohwid_done_
bool warn_nohwid_done_
Definition: eloquent/include/diagnostic_updater/diagnostic_updater.hpp:613
sick_scan_xd_api_test.c
c
Definition: sick_scan_xd_api_test.py:445
diagnostic_updater::DiagnosticTaskVector::DiagnosticTaskInternal::run
void run(diagnostic_updater::DiagnosticStatusWrapper &stat) const
diagnostic_updater::DiagnosticTask::getName
const std::string & getName()
diagnostic_updater::Updater::publish
void publish(diagnostic_msgs::DiagnosticStatus &stat)
std
diagnostic_updater::GenericFunctionDiagnosticTask::name_
const std::string name_
Definition: eloquent/include/diagnostic_updater/diagnostic_updater.hpp:132
diagnostic_updater::CompositeDiagnosticTask::CompositeDiagnosticTask
CompositeDiagnosticTask(const std::string name)
diagnostic_msgs
Definition: AddDiagnostics.h:16
diagnostic_updater::DiagnosticStatusWrapper
Wrapper for the diagnostic_msgs::msg::DiagnosticStatus message that makes it easier to update.
Definition: eloquent/include/diagnostic_updater/diagnostic_status_wrapper.hpp:68
diagnostic_updater::DiagnosticTaskVector::removeByName
bool removeByName(const std::string name)
diagnostic_updater::DiagnosticTaskVector::addInternal
void addInternal(DiagnosticTaskInternal &task)
diagnostic_updater::DiagnosticTaskVector::tasks_
std::vector< DiagnosticTaskInternal > tasks_
Definition: eloquent/include/diagnostic_updater/diagnostic_updater.hpp:328
diagnostic_updater::GenericFunctionDiagnosticTask::run
virtual void run(DiagnosticStatusWrapper &stat)
diagnostic_updater::CompositeDiagnosticTask::run
virtual void run(DiagnosticStatusWrapper &stat)
roswrap::ok
ROSCPP_DECL bool ok()
Check whether it's time to exit.
Definition: rossimu.cpp:273
diagnostic_updater::DiagnosticTaskVector::getTasks
const std::vector< DiagnosticTaskInternal > & getTasks()
diagnostic_updater::Updater::getPeriod
double getPeriod()
diagnostic_updater::DiagnosticTaskVector::add
void add(const std::string &name, TaskFunction f)
diagnostic_msgs::DiagnosticArray
::diagnostic_msgs::DiagnosticArray_< std::allocator< void > > DiagnosticArray
Definition: DiagnosticArray.h:55
sick_scan_xd_simu.status
def status
Definition: sick_scan_xd_simu.py:139


sick_scan_xd
Author(s): Michael Lehning , Jochen Sprickerhof , Martin Günther
autogenerated on Fri Oct 25 2024 02:47:08