2727#include < ros/ros.h>
2828#include < controller_manager/controller_manager.h>
2929
30+ #include < diagnostic_msgs/DiagnosticArray.h>
31+ #include < diagnostic_msgs/DiagnosticStatus.h>
32+ #include < diagnostic_msgs/KeyValue.h>
33+
3034#include < csignal>
3135#include < ur_robot_driver/ros/hardware_interface.h>
3236
@@ -53,6 +57,8 @@ int main(int argc, char** argv)
5357 ros::NodeHandle nh;
5458 ros::NodeHandle nh_priv (" ~" );
5559
60+ ros::Publisher diagnostic_pub = nh.advertise <diagnostic_msgs::DiagnosticArray>(" /diagnostics" , 1 );
61+
5662 // register signal SIGINT and signal handler
5763 signal (SIGINT, signalHandler);
5864
@@ -129,21 +135,161 @@ int main(int argc, char** argv)
129135
130136 double expected_cycle_time = 1.0 / (static_cast <double >(g_hw_interface->getControlFrequency ()));
131137
138+ ros::Duration min_period = ros::Duration (0 );
139+ ros::Duration max_period = ros::Duration (0 );
140+ ros::Duration period_totals = ros::Duration (0 );
141+
142+ std::chrono::duration<double > min_read = std::chrono::duration<double >::zero ();
143+ std::chrono::duration<double > max_read = std::chrono::duration<double >::zero ();
144+ std::chrono::duration<double > read_totals = std::chrono::duration<double >::zero ();
145+ std::chrono::duration<double > min_cm_update = std::chrono::duration<double >::zero ();
146+ std::chrono::duration<double > max_cm_update = std::chrono::duration<double >::zero ();
147+ std::chrono::duration<double > cm_update_totals = std::chrono::duration<double >::zero ();
148+ std::chrono::duration<double > min_write = std::chrono::duration<double >::zero ();
149+ std::chrono::duration<double > max_write = std::chrono::duration<double >::zero ();
150+ std::chrono::duration<double > write_totals = std::chrono::duration<double >::zero ();
151+ long debug_loops = 0 ;
152+
153+ // Debug timing printout every 5 seconds
154+ const std::chrono::seconds debug_timing_period{5 };
155+ std::chrono::steady_clock::time_point debug_timing_start = std::chrono::steady_clock::now ();
156+
132157 // Run as fast as possible
133158 while (ros::ok ())
134159 {
135160 // Receive current state from robot
161+ const std::chrono::steady_clock::time_point read_start = std::chrono::steady_clock::now ();
136162 g_hw_interface->read (timestamp, period);
163+ const std::chrono::duration<double > read_elapsed = std::chrono::steady_clock::now () - read_start;
164+ if (min_read == std::chrono::duration<double >::zero () || read_elapsed < min_read) min_read = read_elapsed;
165+ if (max_read == std::chrono::duration<double >::zero () || read_elapsed > max_read) max_read = read_elapsed;
166+ read_totals += read_elapsed;
137167
138168 // Get current time and elapsed time since last read
139169 timestamp = ros::Time::now ();
140170 stopwatch_now = std::chrono::steady_clock::now ();
141171 period.fromSec (std::chrono::duration_cast<std::chrono::duration<double >>(stopwatch_now - stopwatch_last).count ());
142172 stopwatch_last = stopwatch_now;
143173
174+ const std::chrono::steady_clock::time_point cm_update_start = std::chrono::steady_clock::now ();
144175 cm.update (timestamp, period, g_hw_interface->shouldResetControllers ());
176+ const std::chrono::duration<double > cm_update_elapsed = std::chrono::steady_clock::now () - cm_update_start;
177+ if (min_cm_update == std::chrono::duration<double >::zero () || cm_update_elapsed < min_cm_update) min_cm_update = cm_update_elapsed;
178+ if (max_cm_update == std::chrono::duration<double >::zero () || cm_update_elapsed > max_cm_update) max_cm_update = cm_update_elapsed;
179+ cm_update_totals += cm_update_elapsed;
145180
181+ const std::chrono::steady_clock::time_point write_start = std::chrono::steady_clock::now ();
146182 g_hw_interface->write (timestamp, period);
183+ const std::chrono::duration<double > write_elapsed = std::chrono::steady_clock::now () - write_start;
184+ if (min_write == std::chrono::duration<double >::zero () || write_elapsed < min_write) min_write = write_elapsed;
185+ if (max_write == std::chrono::duration<double >::zero () || write_elapsed > max_write) max_write = write_elapsed;
186+ write_totals += write_elapsed;
187+
188+
189+
190+
191+ if (min_period.isZero () || period < min_period) min_period = period;
192+ if (max_period.isZero () || period > max_period) max_period = period;
193+ period_totals += period;
194+ ++debug_loops;
195+
196+ // Check if it's time to print
197+ const std::chrono::steady_clock::time_point debug_timing_now = std::chrono::steady_clock::now ();
198+ const std::chrono::duration<double > total_elapsed = debug_timing_now - debug_timing_start;
199+ if (total_elapsed > debug_timing_period) {
200+ diagnostic_msgs::DiagnosticArray dia_array;
201+ diagnostic_msgs::DiagnosticStatus robot_status;
202+ robot_status.name = " Driver Timing" ;
203+ robot_status.level = diagnostic_msgs::DiagnosticStatus::OK;
204+ robot_status.message = " Everything seems to be ok." ;
205+
206+ diagnostic_msgs::KeyValue loop_durations_last;
207+ loop_durations_last.key = " Loop durations last (s)" ;
208+ loop_durations_last.value = std::to_string (total_elapsed.count ());
209+ robot_status.values .push_back (loop_durations_last);
210+ diagnostic_msgs::KeyValue num_loops;
211+ num_loops.key = " Number of loops" ;
212+ num_loops.value = std::to_string (debug_loops);
213+ robot_status.values .push_back (num_loops);
214+ diagnostic_msgs::KeyValue min_period_kv;
215+ min_period_kv.key = " min loop period (s)" ;
216+ min_period_kv.value = std::to_string (min_period.toSec ());
217+ robot_status.values .push_back (min_period_kv);
218+ diagnostic_msgs::KeyValue max_period_kv;
219+ max_period_kv.key = " max loop period (s)" ;
220+ max_period_kv.value = std::to_string (max_period.toSec ());
221+ robot_status.values .push_back (max_period_kv);
222+ diagnostic_msgs::KeyValue avg_period_kv;
223+ avg_period_kv.key = " avg loop period (s)" ;
224+ avg_period_kv.value = std::to_string (period_totals.toSec () / debug_loops);
225+ robot_status.values .push_back (avg_period_kv);
226+
227+ diagnostic_msgs::KeyValue min_read_kv;
228+ min_read_kv.key = " min read (s)" ;
229+ min_read_kv.value = std::to_string (min_read.count ());
230+ robot_status.values .push_back (min_read_kv);
231+ diagnostic_msgs::KeyValue max_read_kv;
232+ max_read_kv.key = " max read (s)" ;
233+ max_read_kv.value = std::to_string (max_read.count ());
234+ robot_status.values .push_back (max_read_kv);
235+ diagnostic_msgs::KeyValue avg_read_kv;
236+ avg_read_kv.key = " avg read (s)" ;
237+ avg_read_kv.value = std::to_string (read_totals.count () / debug_loops);
238+ robot_status.values .push_back (avg_read_kv);
239+
240+ diagnostic_msgs::KeyValue min_cm_update_kv;
241+ min_cm_update_kv.key = " min cm_update (s)" ;
242+ min_cm_update_kv.value = std::to_string (min_cm_update.count ());
243+ robot_status.values .push_back (min_cm_update_kv);
244+ diagnostic_msgs::KeyValue max_cm_update_kv;
245+ max_cm_update_kv.key = " max cm_update (s)" ;
246+ max_cm_update_kv.value = std::to_string (max_cm_update.count ());
247+ robot_status.values .push_back (max_cm_update_kv);
248+ diagnostic_msgs::KeyValue avg_cm_update_kv;
249+ avg_cm_update_kv.key = " avg cm_update (s)" ;
250+ avg_cm_update_kv.value = std::to_string (cm_update_totals.count () / debug_loops);
251+ robot_status.values .push_back (avg_cm_update_kv);
252+
253+ diagnostic_msgs::KeyValue min_write_kv;
254+ min_write_kv.key = " min write (s)" ;
255+ min_write_kv.value = std::to_string (min_write.count ());
256+ robot_status.values .push_back (min_write_kv);
257+ diagnostic_msgs::KeyValue max_write_kv;
258+ max_write_kv.key = " max write (s)" ;
259+ max_write_kv.value = std::to_string (max_write.count ());
260+ robot_status.values .push_back (max_write_kv);
261+ diagnostic_msgs::KeyValue avg_write_kv;
262+ avg_write_kv.key = " avg write (s)" ;
263+ avg_write_kv.value = std::to_string (write_totals.count () / debug_loops);
264+ robot_status.values .push_back (avg_write_kv);
265+
266+ dia_array.status .push_back (robot_status);
267+ diagnostic_pub.publish (dia_array);
268+
269+
270+ // ROS_INFO_STREAM(
271+ // "Loop durations last " << total_elapsed.count() << "s: "
272+ // "min=" << min_period.toSec() * 1000.0 << "ms, "
273+ // "max=" << max_period.toSec() * 1000.0 << "ms, "
274+ // "avg=" << period_totals.toSec() * 1000.0 / debug_loops << "ms, "
275+ // "avgchrono=" << total_elapsed.count() * 1000.0 / debug_loops << "ms"
276+ // );
277+ min_period = ros::Duration (0 );
278+ max_period = ros::Duration (0 );
279+ period_totals = ros::Duration (0 );
280+ std::chrono::duration<double > min_read = std::chrono::duration<double >::zero ();
281+ std::chrono::duration<double > max_read = std::chrono::duration<double >::zero ();
282+ std::chrono::duration<double > read_totals = std::chrono::duration<double >::zero ();
283+ std::chrono::duration<double > min_cm_update = std::chrono::duration<double >::zero ();
284+ std::chrono::duration<double > max_cm_update = std::chrono::duration<double >::zero ();
285+ std::chrono::duration<double > cm_update_totals = std::chrono::duration<double >::zero ();
286+ std::chrono::duration<double > min_write = std::chrono::duration<double >::zero ();
287+ std::chrono::duration<double > max_write = std::chrono::duration<double >::zero ();
288+ std::chrono::duration<double > write_totals = std::chrono::duration<double >::zero ();
289+ debug_loops = 0 ;
290+ debug_timing_start = debug_timing_now;
291+ }
292+
147293 // if (!control_rate.sleep())
148294 if (period.toSec () > expected_cycle_time)
149295 {
0 commit comments