RecursiveEstimatorNodeInterface.h
Go to the documentation of this file.
00001 /*
00002  * RecursiveEstimatorNodeInterface.h
00003  *
00004  *      Author: roberto
00005  *
00006  * This is a modified implementation of the method for online estimation of kinematic structures described in our paper
00007  * "Online Interactive Perception of Articulated Objects with Multi-Level Recursive Estimation Based on Task-Specific Priors"
00008  * (Martín-Martín and Brock, 2014).
00009  * This implementation can be used to reproduce the results of the paper and to be applied to new research.
00010  * The implementation allows also to be extended to perceive different information/models or to use additional sources of information.
00011  * A detail explanation of the method and the system can be found in our paper.
00012  *
00013  * If you are using this implementation in your research, please consider citing our work:
00014  *
00015 @inproceedings{martinmartin_ip_iros_2014,
00016 Title = {Online Interactive Perception of Articulated Objects with Multi-Level Recursive Estimation Based on Task-Specific Priors},
00017 Author = {Roberto {Mart\'in-Mart\'in} and Oliver Brock},
00018 Booktitle = {Proceedings of the IEEE/RSJ International Conference on Intelligent Robots and Systems},
00019 Pages = {2494-2501},
00020 Year = {2014},
00021 Location = {Chicago, Illinois, USA},
00022 Note = {http://www.robotics.tu-berlin.de/fileadmin/fg170/Publikationen_pdf/martinmartin_ip_iros_2014.pdf},
00023 Url = {http://www.robotics.tu-berlin.de/fileadmin/fg170/Publikationen_pdf/martinmartin_ip_iros_2014.pdf},
00024 Projectname = {Interactive Perception}
00025 }
00026  * If you have questions or suggestions, contact us:
00027  * roberto.martinmartin@tu-berlin.de
00028  *
00029  * Enjoy!
00030  */
00031 
00032 #ifndef RECURSIVE_ESTIMATOR_NODE_INTERFACE_H_
00033 #define RECURSIVE_ESTIMATOR_NODE_INTERFACE_H_
00034 
00035 #include <vector>
00036 #include <boost/thread.hpp>
00037 #include <ros/ros.h>
00038 #include <ros/callback_queue.h>
00039 #include <ros/node_handle.h>
00040 #include <std_msgs/Empty.h>
00041 
00042 namespace omip
00043 {
00044 
00051 template <class MeasurementTypeROS, class StateTypeROS, class RecursiveEstimatorFilterClass>
00052 class RecursiveEstimatorNodeInterface
00053 {
00054 public:
00055 
00061     RecursiveEstimatorNodeInterface(int num_external_state_predictors) :
00062         _re_filter(NULL),
00063         _num_external_state_predictors(num_external_state_predictors),
00064         _active(true)
00065 
00066     {
00067         // We create a separate node handle with its own callback queue to process the measurement (only 1 type of measurement?)
00068         this->_measurements_queue = ros::getGlobalCallbackQueue();
00069         this->_measurements_node_handle.setCallbackQueue(this->_measurements_queue);
00070 
00071         // We want to process the predictions about the state as soon as they arrive
00072         // Therefore, we create a separate node handle with separate callback queues for each external state predictor
00073         this->_state_prediction_node_handles.resize(this->_num_external_state_predictors);
00074         this->_state_prediction_queues.resize(this->_num_external_state_predictors, NULL);
00075         for(int num_external_state_predictors_idx = 0; num_external_state_predictors_idx < this->_num_external_state_predictors; num_external_state_predictors_idx++)
00076         {
00077             this->_state_prediction_queues.at(num_external_state_predictors_idx) = new ros::CallbackQueue(true);
00078             this->_state_prediction_node_handles.at(num_external_state_predictors_idx).setCallbackQueue((this->_state_prediction_queues.at(num_external_state_predictors_idx)));
00079         }
00080 
00081         this->_current_measurement_time.fromNSec(0);
00082         this->_previous_measurement_time.fromNSec(0);
00083 
00084         // All nodes subscribe to the "shutdown" signal
00085         this->_node_quit_subscriber = this->_measurements_node_handle.subscribe("/omip/shutdown", 1, &RecursiveEstimatorNodeInterface::quitCallback, this);
00086     }
00087 
00092     virtual ~RecursiveEstimatorNodeInterface()
00093     {
00094         if(this->_re_filter)
00095         {
00096             delete this->_re_filter;
00097             this->_re_filter = NULL;
00098         }
00099     }
00100 
00105     virtual void run()
00106     {
00107         // For each predictor of states...
00108         for(int idx = 0; idx < this->_num_external_state_predictors; idx++)
00109         {
00110             // ... we create a thread that spins on the callback queue of the predictor
00111             this->_state_predictor_listener_threads.push_back(new boost::thread(boost::bind(&RecursiveEstimatorNodeInterface::spinStatePredictorQueue, this, idx)));
00112         }
00113         // Spin here the queue of the measurements
00114         while (ros::ok() && this->_active)
00115         {
00116             //ros::getGlobalCallbackQueue()->callAvailable(ros::WallDuration(0.1));
00117             this->_measurements_queue->callAvailable(ros::WallDuration(0.005));
00118         }
00119     }
00120 
00126     virtual void spinStatePredictorQueue(int state_prediction_queue_idx)
00127     {
00128         while (ros::ok() && this->_active)
00129         {
00130             this->_state_prediction_queues.at(state_prediction_queue_idx)->callAvailable(ros::WallDuration(0.01));
00131         }
00132     }
00133 
00139     virtual void measurementCallback(const boost::shared_ptr<MeasurementTypeROS const> & measurement) = 0;
00140 
00146     virtual void statePredictionCallback(const boost::shared_ptr<StateTypeROS const> & predicted_next_state) = 0;
00147 
00153     virtual void quitCallback(const std_msgs::EmptyConstPtr &msg)
00154     {
00155         ROS_INFO_STREAM("RecursiveEstimatorNode stopping!");
00156         _active = false;
00157     }
00158 
00162     template<class T>
00163     bool getROSParameter(std::string param_name, T & param_container)
00164     {
00165         if (!(this->_measurements_node_handle.getParam(param_name, param_container)))
00166         {
00167             ROS_ERROR("The parameter %s can not be found.", param_name.c_str());
00168             throw(std::string("The parameter can not be found. Parameter name: ") + param_name);
00169             return false;
00170         }
00171         else
00172             return true;
00173     }
00174 
00178     template<class T>
00179     bool getROSParameter(std::string param_name, T & param_container, const T & default_value)
00180     {
00181         if (!(this->_measurements_node_handle.getParam(param_name, param_container)))
00182         {
00183             ROS_WARN_STREAM("The parameter " << param_name <<" can not be found. Using the default value " << default_value );
00184             param_container = default_value;
00185             return false;
00186         }
00187         else
00188             return true;
00189     }
00190 
00191 protected:
00192 
00197     virtual void _publishState() const = 0;
00198 
00203     virtual void _publishPredictedMeasurement() const = 0;
00204 
00205 
00206     RecursiveEstimatorFilterClass* _re_filter;
00207 
00208     std::string _namespace;
00209 
00210     // We create a separate thread to listen to a separate queue where the state predictions from higher level will arrive
00211     // Right now the hierarchy that I developed uses only one prediction from higher levels, but nobody knows how it will evolve ;)
00212     int _num_external_state_predictors;
00213     std::vector<ros::NodeHandle> _state_prediction_node_handles;
00214     std::vector<ros::CallbackQueue*> _state_prediction_queues;
00215     std::vector<boost::thread*> _state_predictor_listener_threads;
00216 
00217     // We have only one subscriber for state predictions (how to create several of them?)
00218     ros::Subscriber _measurement_subscriber;
00219     ros::Subscriber _state_prediction_subscriber;
00220     ros::Subscriber _node_quit_subscriber;
00221     ros::Publisher _state_publisher;
00222     ros::Publisher _state_prediction_publisher;
00223     ros::Publisher _measurement_prediction_publisher;
00224 
00225     // I have to set the measurement queue to be the global queue so that the dynamic reconfigure works
00226     // That is done in the constructor
00227     ros::CallbackQueue* _measurements_queue;
00228     ros::NodeHandle _measurements_node_handle;
00229 
00230     // These 2 times contain the time of the previous and current measurement that are processed
00231     ros::Time       _current_measurement_time;
00232     ros::Time       _previous_measurement_time;
00233     ros::Duration   _loop_period_ns;
00234 
00235     bool            _active;
00236 };
00237 }
00238 
00239 #endif /* RECURSIVE_ESTIMATOR_NODE_INTERFACE_H_ */


omip_common
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:26:37