example.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  * 
00004  *  Copyright (c) 2008, Willow Garage, Inc.
00005  *  All rights reserved.
00006  * 
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  * 
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the Willow Garage nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  * 
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 
00035 #include <diagnostic_updater/diagnostic_updater.h>
00036 #include <std_msgs/Bool.h>
00037 #include <diagnostic_updater/publisher.h>
00038 
00039 // ERROR defined in windows.h causes name collision, undefine the macro to fix the issue
00040 #ifdef ERROR
00041 #undef ERROR
00042 #endif
00043 
00044 double time_to_launch;
00045 
00046 /*
00047  *\brief Used as a tutorial for loading and using diagnostic updater
00048  *
00049  * DummyClass and dummy_diagnostics show how to use a diagnostic_updater
00050  * class.
00051  */
00052 
00053 void dummy_diagnostic(diagnostic_updater::DiagnosticStatusWrapper &stat)
00054 {
00055   // DiagnosticStatusWrapper are a derived class of 
00056   // diagnostic_msgs::DiagnosticStatus provides a set of convenience
00057   // methods.
00058   
00059   // summary and summaryf set the level and message.
00060   if (time_to_launch < 10)
00061     // summaryf for formatted text.
00062     stat.summaryf(diagnostic_msgs::DiagnosticStatus::ERROR, "Buckle your seat belt. Launch in %f seconds!", time_to_launch);
00063   else
00064     // summary for unformatted text.
00065     stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Launch is in a long time. Have a soda.");
00066 
00067   // add and addf are used to append key-value pairs.
00068   stat.add("Diagnostic Name", "dummy");
00069   // add transparently handles conversion to string (using a string_stream).
00070   stat.add("Time to Launch", time_to_launch);
00071   // addf allows arbitrary printf style formatting.
00072   stat.addf("Geeky thing to say", "The square of the time to launch %f is %f", 
00073       time_to_launch, time_to_launch * time_to_launch);
00074 }
00075 
00076 class DummyClass
00077 {
00078 public:
00079   void produce_diagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
00080   {
00081     stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "This is a silly updater.");
00082 
00083     stat.add("Stupidicity of this updater", 1000.);
00084   }
00085 };
00086 
00087 class DummyTask : public diagnostic_updater::DiagnosticTask
00088 {
00089 public:
00090   DummyTask() : DiagnosticTask("Updater Derived from DiagnosticTask")
00091   {}
00092 
00093   void run(diagnostic_updater::DiagnosticStatusWrapper &stat)
00094   {
00095     stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "This is another silly updater.");
00096     stat.add("Stupidicity of this updater", 2000.);
00097   }
00098 };
00099 
00100 void check_lower_bound(diagnostic_updater::DiagnosticStatusWrapper &stat)
00101 {
00102   if (time_to_launch > 5)
00103     stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Lower-bound OK");
00104   else
00105     stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "Too low");
00106 
00107   stat.add("Low-Side Margin", time_to_launch - 5);
00108 }
00109 
00110 void check_upper_bound(diagnostic_updater::DiagnosticStatusWrapper &stat)
00111 {
00112   if (time_to_launch < 10)
00113     stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "Upper-bound OK");
00114   else
00115     stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "Too high");
00116 
00117   stat.add("Top-Side Margin", 10 - time_to_launch);
00118 }
00119 
00120 int main(int argc, char **argv)
00121 {
00122   ros::init(argc, argv, "diagnostic_updater_example");
00123   
00124   ros::NodeHandle nh;
00125   
00126   // The Updater class advertises to /diagnostics, and has a
00127   // ~diagnostic_period parameter that says how often the diagnostics
00128   // should be published.
00129   diagnostic_updater::Updater updater;
00130 
00131   // The diagnostic_updater::Updater class will fill out the hardware_id
00132   // field of the diagnostic_msgs::DiagnosticStatus message. You need to
00133   // use the setHardwareID() or setHardwareIDf() methods to set the
00134   // hardware ID. 
00135   //
00136   // The hardware ID should be able to identify the specific device you are
00137   // working with.  If it is not appropriate to fill out a hardware ID in
00138   // your case, you should call setHardwareIDf("none") to avoid warnings.
00139   // (A warning will be generated as soon as your node updates with no
00140   // non-OK statuses.)
00141   updater.setHardwareID("none"); 
00142   // Or...
00143   updater.setHardwareIDf("Device-%i-%i", 27, 46);
00144 
00145   // Diagnostic tasks are added to the Updater. They will later be run when
00146   // the updater decides to update. The add method is heavily overloaded
00147   // for convenienc. Check doxygen for the full list of add methods.
00148   updater.add("Function updater", dummy_diagnostic);
00149   DummyClass dc;
00150   updater.add("Method updater", &dc, &DummyClass::produce_diagnostics);
00151   
00152   // Internally, updater.add converts its arguments into a DiagnosticTask.
00153   // Sometimes it can be useful to work directly with DiagnosticTasks. Look
00154   // at FrequencyStatus and TimestampStatus in update_functions.h for a
00155   // real-life example of how to make a DiagnosticTask by deriving from
00156   // DiagnosticTask.
00157   
00158   // Alternatively, a FunctionDiagnosticTask is a derived class from
00159   // DiagnosticTask that can be used to create a DiagnosticTask from
00160   // a function. This will be useful when combining multiple diagnostic
00161   // tasks using a CompositeDiagnosticTask.
00162   diagnostic_updater::FunctionDiagnosticTask lower("Lower-bound check",
00163       boost::bind(&check_lower_bound, _1));
00164   diagnostic_updater::FunctionDiagnosticTask upper("Upper-bound check",
00165       boost::bind(&check_upper_bound, _1));
00166 
00167   // If you want to merge the outputs of two diagnostic tasks together, you
00168   // can create a CompositeDiagnosticTask, also a derived class from
00169   // DiagnosticTask. For example, we could combine the upper and lower
00170   // bounds check into a single DiagnosticTask.
00171   diagnostic_updater::CompositeDiagnosticTask bounds("Bound check");
00172   bounds.addTask(&lower);
00173   bounds.addTask(&upper);
00174 
00175   // We can then add the CompositeDiagnosticTask to our Updater. When it is
00176   // run, the overall name will be the name of the composite task, i.e., 
00177   // "Bound check". The summary will be a combination of the summary of the
00178   // lower and upper tasks (see \ref
00179   // DiagnosticStatusWrapper::mergeSummarSummary for details on how the
00180   // merging is done). The lists of key-value pairs will be concatenated.
00181   updater.add(bounds);
00182 
00183   // You can broadcast a message in all the DiagnosticStatus if your node
00184   // is in a special state.
00185   updater.broadcast(0, "Doing important initialization stuff.");
00186 
00187   ros::Publisher pub1 = nh.advertise<std_msgs::Bool>("topic1", 1);
00188   ros::Publisher pub2_temp = nh.advertise<std_msgs::Bool>("topic2", 1);
00189   ros::Duration(2).sleep(); // It isn't important if it doesn't take time.
00190 
00191   // Some diagnostic tasks are very common, such as checking the rate
00192   // at which a topic is publishing, or checking that timestamps are
00193   // sufficiently recent. FrequencyStatus and TimestampStatus can do these
00194   // checks for you. 
00195   //
00196   // Usually you would instantiate them via a HeaderlessTopicDiagnostic
00197   // (FrequencyStatus only, for topics that do not contain a header) or a
00198   // TopicDiagnostic (FrequencyStatus and TimestampStatus, for topics that
00199   // do contain a header). 
00200   //
00201   // Some values are passed to the constructor as pointers. If these values
00202   // are changed, the FrequencyStatus/TimestampStatus will start operating
00203   // with the new values. 
00204   //
00205   // Refer to diagnostic_updater::FrequencyStatusParam and
00206   // diagnostic_updater::TimestampStatusParam documentation for details on
00207   // what the parameters mean:
00208   double min_freq = 0.5; // If you update these values, the
00209   double max_freq = 2; // HeaderlessTopicDiagnostic will use the new values.
00210   diagnostic_updater::HeaderlessTopicDiagnostic pub1_freq("topic1", updater,
00211       diagnostic_updater::FrequencyStatusParam(&min_freq, &max_freq, 0.1, 10));
00212 
00213   // Note that TopicDiagnostic, HeaderlessDiagnosedPublisher,
00214   // HeaderlessDiagnosedPublisher and DiagnosedPublisher all descend from
00215   // CompositeDiagnosticTask, so you can add your own fields to them using
00216   // the addTask method.
00217   //
00218   // Each time pub1_freq is updated, lower will also get updated and its
00219   // output will be merged with the output from pub1_freq.
00220   pub1_freq.addTask(&lower); // (This wouldn't work if lower was stateful).
00221 
00222   // If we know that the state of the node just changed, we can force an
00223   // immediate update.
00224   updater.force_update();
00225 
00226   // We can remove a task by refering to its name.
00227   if (!updater.removeByName("Bound check"))
00228     ROS_ERROR("The Bound check task was not found when trying to remove it.");
00229 
00230   while (nh.ok())
00231   {
00232     std_msgs::Bool msg;
00233     ros::Duration(0.1).sleep();
00234     
00235     // Calls to pub1 have to be accompanied by calls to pub1_freq to keep
00236     // the statistics up to date.
00237     msg.data = false;
00238     pub1.publish(msg);
00239     pub1_freq.tick();
00240 
00241     // We can call updater.update whenever is convenient. It will take care
00242     // of rate-limiting the updates.
00243     updater.update();
00244   }
00245 
00246   return 0; 
00247 }


diagnostic_updater
Author(s): Kevin Watts, Brice Rebsamen , Jeremy Leibs, Blaise Gassend
autogenerated on Tue Mar 26 2019 03:09:44