35 #ifndef DIAGNOSTIC_UPDATER__DIAGNOSTIC_UPDATER_HPP_
36 #define DIAGNOSTIC_UPDATER__DIAGNOSTIC_UPDATER_HPP_
44 #include "builtin_interfaces/msg/time.hpp"
46 #include "diagnostic_msgs/msg/diagnostic_array.hpp"
47 #include "diagnostic_msgs/msg/diagnostic_status.hpp"
49 #include "diagnostic_updater/diagnostic_status_wrapper.hpp"
53 #include "rclcpp/create_timer.hpp"
54 #include "rclcpp/rclcpp.hpp"
59 typedef std::function<void (DiagnosticStatusWrapper &)>
TaskFunction;
97 const std::string
name_;
112 class GenericFunctionDiagnosticTask :
public DiagnosticTask
124 const std::string &
name,
125 std::function<
void(T &)> fn)
128 virtual void run(DiagnosticStatusWrapper & stat) {
fn_(stat);}
131 const std::string
name_;
135 typedef GenericFunctionDiagnosticTask<diagnostic_msgs::msg::DiagnosticStatus>
137 typedef GenericFunctionDiagnosticTask<DiagnosticStatusWrapper>
152 class CompositeDiagnosticTask :
public DiagnosticTask
164 virtual void run(DiagnosticStatusWrapper & stat)
166 DiagnosticStatusWrapper combined_summary;
167 DiagnosticStatusWrapper original_summary;
169 original_summary.summary(stat);
171 for (std::vector<DiagnosticTask *>::iterator i =
tasks_.begin();
175 stat.summary(original_summary);
179 combined_summary.mergeSummary(stat);
183 stat.summary(combined_summary);
195 std::vector<DiagnosticTask *>
tasks_;
206 class DiagnosticTaskVector
213 class DiagnosticTaskInternal
237 const std::vector<DiagnosticTaskInternal> &
getTasks() {
return tasks_;}
240 virtual ~DiagnosticTaskVector() {}
255 DiagnosticTaskInternal int_task(
name, f);
266 void add(DiagnosticTask & task)
269 add(task.getName(), f);
287 const std::string
name, T *
c,
290 DiagnosticTaskInternal int_task(
name, std::bind(f,
c, std::placeholders::_1));
306 std::unique_lock<std::mutex> lock(
lock_);
307 for (std::vector<DiagnosticTaskInternal>::iterator iter =
tasks_.begin();
308 iter !=
tasks_.end(); iter++)
310 if (iter->getName() ==
name) {
327 std::vector<DiagnosticTaskInternal>
tasks_;
335 std::unique_lock<std::mutex> lock(
lock_);
352 class Updater :
public DiagnosticTaskVector
365 template<
class NodeT>
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(),
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,
384 base_interface_(base_interface),
385 timers_interface_(timers_interface),
386 clock_(
std::make_shared<rclcpp::Clock>(RCL_ROS_TIME)),
390 topics_interface,
"/diagnostics", 1)),
391 logger_(logging_interface->get_logger()),
395 period = parameters_interface->declare_parameter(
396 "diagnostic_updater.period", rclcpp::ParameterValue(period)).get<
double>();
397 period_ = rclcpp::Duration::from_nanoseconds(period * 1e9);
419 void setPeriod(
double period)
421 setPeriod(rclcpp::Duration::from_nanoseconds(period * 1e9));
442 void broadcast(
int lvl,
const std::string msg)
444 std::vector<diagnostic_msgs::msg::DiagnosticStatus> status_vec;
446 const std::vector<DiagnosticTaskInternal> & tasks =
getTasks();
447 for (std::vector<DiagnosticTaskInternal>::const_iterator iter =
449 iter != tasks.end(); iter++)
453 status.name = iter->getName();
456 status_vec.push_back(
status);
465 const int kBufferSize = 1000;
466 char buff[kBufferSize];
467 va_start(va, format);
468 if (vsnprintf(buff, kBufferSize, format, va) >= kBufferSize) {
469 RCLCPP_DEBUG(logger_,
"Really long string in diagnostic_updater::setHardwareIDf.");
471 hwid_ = std::string(buff);
480 update_timer_ = rclcpp::create_timer(
495 bool warn_nohwid =
hwid_.empty();
497 std::vector<diagnostic_msgs::msg::DiagnosticStatus> status_vec;
499 std::unique_lock<std::mutex> lock(
501 const std::vector<DiagnosticTaskInternal> & tasks =
getTasks();
502 for (std::vector<DiagnosticTaskInternal>::const_iterator iter =
504 iter != tasks.end(); iter++)
508 status.name = iter->getName();
510 status.message =
"No message was set";
515 status_vec.push_back(
status);
523 logger_,
"Non-zero diagnostic status. Name: '%s', status %i: '%s'",
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());
559 std::vector<diagnostic_msgs::msg::DiagnosticStatus> status_vec;
560 status_vec.push_back(stat);
567 void publish(std::vector<diagnostic_msgs::msg::DiagnosticStatus> & status_vec)
569 for (std::vector<diagnostic_msgs::msg::DiagnosticStatus>::iterator iter =
571 iter != status_vec.end(); iter++)
573 iter->name =
node_name_ + std::string(
": ") + iter->name;
576 msg.status = status_vec;
577 msg.header.stamp = rclcpp::Clock().now();
587 DiagnosticStatusWrapper stat;
588 stat.name = task.getName();
589 stat.summary(0,
"Node starting up");
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_;
607 #endif // DIAGNOSTIC_UPDATER__DIAGNOSTIC_UPDATER_HPP_