iri_base_algorithm.h
Go to the documentation of this file.
00001 // Copyright (C) 2010-2011 Institut de Robotica i Informatica Industrial, CSIC-UPC.
00002 // Author Joan Perez
00003 // All rights reserved.
00004 //
00005 // This file is part of iri-ros-pkg
00006 // iri-ros-pkg is free software: you can redistribute it and/or modify
00007 // it under the terms of the GNU Lesser General Public License as published by
00008 // the Free Software Foundation, either version 3 of the License, or
00009 // at your option) any later version.
00010 //
00011 // This program is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public License
00017 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018 
00019 #ifndef _IRI_BASE_ALGORITHM_H
00020 #define _IRI_BASE_ALGORITHM_H
00021 
00022 #include <ros/ros.h>
00023 #include <signal.h>
00024 
00025 // boost thread includes for ROS::spin thread
00026 #include <boost/thread.hpp>
00027 #include <boost/bind.hpp>
00028 
00029 // dynamic reconfigure server include
00030 #include <dynamic_reconfigure/server.h>
00031 
00032 // diagnostic updater include
00033 #include <diagnostic_updater/diagnostic_updater.h>
00034 
00035 namespace algorithm_base
00036 {
00037 
00042 class AbstractAlgorithmNode
00043 {
00044   protected:
00045     static int ctrl_c_hit_count_;
00046     
00047     static void hupCalled(int sig)
00048     {
00049       ROS_WARN("Unexpected SIGHUP caught. Ignoring it.");
00050     }
00051     
00052     static void sigCalled(int sig)
00053     {
00054       ctrl_c_hit_count_++;
00055     }
00056 };
00057 
00082 template <class Algorithm>
00083 class IriBaseAlgorithm : public AbstractAlgorithmNode
00084 {
00085   public:
00093     typedef typename Algorithm::Config Config;
00094 
00095   protected:
00104     pthread_t thread;
00105 
00113     Algorithm alg_;
00114 
00122     ros::NodeHandle public_node_handle_;
00123 
00131     ros::NodeHandle private_node_handle_;
00132 
00141     ros::Rate loop_rate_;
00142 
00149     static const unsigned int DEFAULT_RATE = 10; //[Hz]
00150     
00157     diagnostic_updater::Updater diagnostic_;
00158 
00159   public:
00167     IriBaseAlgorithm(void);
00168 
00174     ~IriBaseAlgorithm(void);
00175 
00183     int spin(void);
00184 
00185   private:
00192     boost::shared_ptr<boost::thread> ros_thread_;
00193 
00200     dynamic_reconfigure::Server<Config> dsrv_;
00201 
00202   protected:
00215     void reconfigureCallback(Config &config, uint32_t level);
00216 
00229     virtual void node_config_update(Config &config, uint32_t level) = 0;
00230    
00237     void addDiagnostics(void);
00238 
00245     virtual void addNodeDiagnostics(void) = 0;
00246 
00247 //     void addOpenedTests(void);
00248 //     void addStoppedTests(void);
00249 //     void addRunningTests(void);
00250 //     virtual void addNodeOpenedTests(void) = 0;
00251 //     virtual void addNodeStoppedTests(void) = 0;
00252 //     virtual void addNodeRunningTests(void) = 0;
00253 
00267     static void *mainThread(void *param);
00268 
00275     virtual void mainNodeThread(void) = 0;
00276 };
00277 
00278 
00279 template <class Algorithm>
00280 IriBaseAlgorithm<Algorithm>::IriBaseAlgorithm() : 
00281   public_node_handle_(ros::this_node::getName()),
00282   private_node_handle_("~"), 
00283   loop_rate_(DEFAULT_RATE),
00284   diagnostic_(),
00285   dsrv_(private_node_handle_)
00286 {
00287   ROS_DEBUG("IriBaseAlgorithm::Constructor");
00288 
00289   // create the status thread
00290   pthread_create(&this->thread,NULL,this->mainThread,this);
00291 
00292 //   // assign callback to dynamic reconfigure server
00293 //   dsrv_.setCallback(boost::bind(&IriBaseAlgorithm<Algorithm>::reconfigureCallback, this, _1, _2));
00294 
00295 }
00296 
00297 template <class Algorithm>
00298 IriBaseAlgorithm<Algorithm>::~IriBaseAlgorithm()
00299 {
00300   ROS_DEBUG("IriBaseAlgorithm::Destructor");
00301   pthread_cancel(this->thread);
00302   pthread_join(this->thread,NULL);
00303 }
00304 
00305 template <class Algorithm>
00306 void IriBaseAlgorithm<Algorithm>::reconfigureCallback(Config &config, uint32_t level)
00307 {
00308   ROS_DEBUG("IriBaseAlgorithm::reconfigureCallback");
00309   this->node_config_update(config, level);
00310   this->alg_.config_update(config, level);
00311 }
00312 
00313 template <class Algorithm>
00314 void IriBaseAlgorithm<Algorithm>::addDiagnostics(void)
00315 {
00316   ROS_DEBUG("IriBaseAlgorithm::addDiagnostics");
00317   addNodeDiagnostics();
00318 }
00319 
00320 template <class Algorithm>
00321 void *IriBaseAlgorithm<Algorithm>::mainThread(void *param)
00322 {
00323   ROS_DEBUG("IriBaseAlgorithm::mainThread");
00324 
00325   // retrieve base algorithm class
00326   IriBaseAlgorithm *iriNode = (IriBaseAlgorithm *)param;
00327 
00328   while(ros::ok() && !ctrl_c_hit_count_)
00329   {
00330     // run node stuff
00331     iriNode->mainNodeThread();
00332 
00333     // sleep remainder time
00334     iriNode->loop_rate_.sleep();
00335   }
00336 
00337   // kill main thread
00338   pthread_exit(NULL);
00339 }
00340 
00341 template <class Algorithm>
00342 int IriBaseAlgorithm<Algorithm>::spin(void)
00343 {
00344   ROS_DEBUG("IriBaseAlgorithm::spin");
00345 
00346   // initialize diagnostics
00347   this->diagnostic_.setHardwareID("none");
00348   this->addDiagnostics();
00349   
00350   // launch ros spin in different thread
00351   this->ros_thread_.reset( new boost::thread(boost::bind(&ros::spin)) );
00352   assert(ros_thread_);
00353 
00354   // assign callback to dynamic reconfigure server
00355   this->dsrv_.setCallback(boost::bind(&IriBaseAlgorithm<Algorithm>::reconfigureCallback, this, _1, _2));
00356 
00357   while(ros::ok() && !ctrl_c_hit_count_)
00358   {
00359     // update diagnostics
00360     this->diagnostic_.update();
00361     
00362     ros::WallDuration(0.1).sleep();
00363   }
00364 
00365   // stop ros
00366   ros::shutdown();
00367 
00368   // kill ros spin thread
00369   this->ros_thread_.reset();
00370 
00371   return 0;
00372 }
00373 
00374 // definition of the static Ctrl+C counter
00375 int AbstractAlgorithmNode::ctrl_c_hit_count_ = 0;
00376 
00391 template <class AlgImplTempl>
00392 int main(int argc, char **argv, std::string node_name)
00393 {
00394   ROS_DEBUG("IriBaseAlgorithm::%s Launched", node_name.c_str());
00395 
00396   // ROS initialization
00397   ros::init(argc, argv, node_name);
00398 
00399   // allow Ctrl+C management
00400   signal(SIGHUP, &AbstractAlgorithmNode::hupCalled);
00401 
00402   // define and launch generic algorithm implementation object
00403   AlgImplTempl algImpl;
00404   algImpl.spin();
00405 
00406   return 0;
00407 }
00408 
00409 }
00410 #endif


iri_base_algorithm
Author(s): Joan Perez, jnperez at iri.upc.edu
autogenerated on Fri Dec 6 2013 19:54:27