feelforce.cpp
Go to the documentation of this file.
00001 /*
00002 Author: Minglong Li
00003 Affiliation: State Key Laboratory of High Performance Computing (HPCL)
00004              College of Computer, National University of Defense Technology
00005 Email: minglong_l@163.com
00006 Created on: July 11th, 2016
00007 */
00008 #include <ros/ros.h>
00009 #include <nodelet/nodelet.h>
00010 #include <limits> 
00011 #include <iostream>
00012 #include <pluginlib/class_list_macros.h>
00013 
00014 #include <vector>
00015 #include <algorithm>
00016 #include <functional> 
00017 #include <math.h>
00018 
00019 #include <message_filters/subscriber.h>
00020 #include <message_filters/synchronizer.h>
00021 #include <message_filters/sync_policies/approximate_time.h>
00022 
00023 #include <sensor_msgs/Range.h>
00024 #include <micros_mars_task_alloc/Force.h>
00025 
00026 namespace micros_mars_task_alloc {
00027 using namespace sensor_msgs;
00028 using namespace message_filters;
00029 using namespace std;
00030 
00031 class Feelforce : public nodelet::Nodelet
00032 {
00033 public:
00034     Feelforce(): maximum_queue_size_(10), min_range_(0.3), max_range_(3.0), pi_(std::acos(-1)){}
00035     ~Feelforce(){}
00036 
00037     virtual void onInit();
00038 
00039     
00040    //Because message_filters support 9 topics at most, use two filters and two callbacks to handle the sonar messages.
00041     void callback_0(const RangeConstPtr& msg_0, const RangeConstPtr& msg_1, const RangeConstPtr& msg_2, 
00042                     const RangeConstPtr& msg_3, const RangeConstPtr& msg_4, const RangeConstPtr& msg_5); 
00043     void callback_1(const RangeConstPtr& msg_0, const RangeConstPtr& msg_1, const RangeConstPtr& msg_2, 
00044                     const RangeConstPtr& msg_3, const RangeConstPtr& msg_4, const RangeConstPtr& msg_5);                                              
00045 
00046     void timerCallback(const ros::TimerEvent&);
00047     //This struct is used to sum the feelforce and has higher efficiency.    
00048     typedef struct force
00049     {
00050         float range;
00051         float angle;
00052     }Force;
00053     //The synchronizing policy is approximate.
00054 private:
00055     //every force has a range and an angle.
00056 
00057     typedef sync_policies::ApproximateTime<Range, Range, Range, Range, Range, Range> ApproximatePolicy;
00058     typedef message_filters::Synchronizer<ApproximatePolicy> ApproximateSync;
00059     
00060     //Because message_filters support 9 topics at most, use two filters and two callbacks to handle the sonar messages.
00061     boost::shared_ptr<ApproximateSync> approximate_sync_1_;    
00062     boost::shared_ptr<ApproximateSync> approximate_sync_2_;
00063     
00064     float pi_;
00065     int maximum_queue_size_;//control the queue size of the message filters
00066     float min_range_;//if the sensed distance is smaller than the minimum distance, assign it the parameter
00067     float max_range_;//if the sensed distance is larger than the max distance, assign it the parameter
00068 
00069     float r_[12];//store the range of the 12 sensor messages.
00070 
00071     message_filters::Subscriber<Range> sub_0_, sub_1_, sub_2_, sub_3_, sub_4_, sub_5_, sub_6_, sub_7_, sub_8_, sub_9_, sub_10_, sub_11_;
00072     ros::Timer timer_;
00073     ros::NodeHandle nh_;
00074     ros::Publisher pub_;
00075 
00076 };
00077 
00078 void Feelforce::onInit()
00079 {
00080     nh_ = getPrivateNodeHandle();
00081     cout << "Initialising nodelet ..." << endl;        
00082 
00083     //The topics should be absolute.
00084     sub_0_.subscribe(nh_, "/robot0/sonar_0", 1);
00085     sub_1_.subscribe(nh_, "/robot0/sonar_1", 1);
00086     sub_2_.subscribe(nh_, "/robot0/sonar_2", 1);
00087     sub_3_.subscribe(nh_, "/robot0/sonar_3", 1);   
00088     sub_4_.subscribe(nh_, "/robot0/sonar_4", 1);
00089     sub_5_.subscribe(nh_, "/robot0/sonar_5", 1);
00090     sub_6_.subscribe(nh_, "/robot0/sonar_6", 1);
00091     sub_7_.subscribe(nh_, "/robot0/sonar_7", 1);   
00092     sub_8_.subscribe(nh_, "/robot0/sonar_8", 1);
00093     sub_9_.subscribe(nh_, "/robot0/sonar_9", 1);
00094     sub_10_.subscribe(nh_, "/robot0/sonar_10", 1);
00095     sub_11_.subscribe(nh_, "/robot0/sonar_11", 1);   
00096     
00097     approximate_sync_1_.reset( new ApproximateSync(ApproximatePolicy(maximum_queue_size_), sub_0_, sub_1_, sub_2_, sub_3_, sub_4_, sub_5_ ) );
00098     approximate_sync_1_->registerCallback(boost::bind(&Feelforce::callback_0, this, _1, _2, _3, _4, _5, _6));
00099     
00100     approximate_sync_2_.reset( new ApproximateSync(ApproximatePolicy(maximum_queue_size_), sub_6_, sub_7_, sub_8_, sub_9_, sub_10_, sub_11_ ) );
00101     approximate_sync_2_->registerCallback(boost::bind(&Feelforce::callback_1, this, _1, _2, _3, _4, _5, _6));    
00102     
00103     timer_ = nh_.createTimer(ros::Duration(0.1), &Feelforce::timerCallback, this);
00104 
00105 }
00106 
00107 void Feelforce::callback_0(const RangeConstPtr& msg_0, const RangeConstPtr& msg_1, const RangeConstPtr& msg_2, 
00108                            const RangeConstPtr& msg_3, const RangeConstPtr& msg_4, const RangeConstPtr& msg_5)
00109 {
00110     //cout << "callback_0 start!" << endl;
00111     r_[0] = msg_0 -> range;
00112     r_[1] = msg_1 -> range;
00113     r_[2] = msg_2 -> range;
00114     r_[3] = msg_3 -> range;    
00115     r_[4] = msg_4 -> range;
00116     r_[5] = msg_5 -> range;
00117 }
00118 
00119 void Feelforce::callback_1(const RangeConstPtr& msg_0, const RangeConstPtr& msg_1, const RangeConstPtr& msg_2, 
00120                            const RangeConstPtr& msg_3, const RangeConstPtr& msg_4, const RangeConstPtr& msg_5)
00121 {
00122     //cout << "callback_1 start" << endl;
00123     r_[6] = msg_0 -> range;
00124     r_[7] = msg_1 -> range;
00125     r_[8] = msg_2 -> range;
00126     r_[9] = msg_3 -> range;    
00127     r_[10] = msg_4 -> range;
00128     r_[11] = msg_5 -> range;
00129 }
00130 
00131 void Feelforce::timerCallback(const ros::TimerEvent&)
00132 {
00133     vector<Force> vec;
00134     
00135     float rectangular_coordinates_sum_x = 0;
00136     float rectangular_coordinates_sum_y = 0;
00137     for (int i = 0; i < 12; i++)
00138     {
00139         Force a;
00140         /*
00141         Fixed distance rangers only output -Inf or +Inf.
00142         -Inf represents a detection within fixed distance.
00143         (Detection too close to the sensor to quantify)
00144         +Inf represents no detection within the fixed distance.
00145         (Object out of range)
00146         */
00147         if (r_[i] == std::numeric_limits<float>::infinity()) 
00148             a.range = max_range_;
00149         else if (r_[i] == -std::numeric_limits<float>::infinity())
00150             a.range = min_range_;
00151         else
00152             a.range = r_[i];
00153 
00154         a.angle = i * 30.0;
00155         vec.push_back(a);
00156     }
00157     //variable capture: notice that the lambda function uses the variable in the outside block, and capture the this ptr.
00158     for_each(vec.begin(), vec.end(), [&, this](const Force& val)->void
00159     {
00160         //cout << "val.range: " << val.range << endl; 
00161         //cout << "std::cos(pi_ * val.angle / 180.0) :" << std::cos(pi_ * val.angle / 180.0) << endl;
00162         //cout << "(1/(val.range*val.range)) * std::cos(pi_ * val.angle / 180.0)" << (1/(val.range*val.range)) * std::cos(pi_ * val.angle / 180.0) << endl;
00163         rectangular_coordinates_sum_x += (1/(val.range*val.range)) * std::cos(pi_ * val.angle / 180.0);//TODO:pi?
00164         rectangular_coordinates_sum_y += (1/(val.range*val.range)) * std::sin(pi_ * val.angle / 180.0);        
00165     });
00166     rectangular_coordinates_sum_x = (-1) * rectangular_coordinates_sum_x;
00167         rectangular_coordinates_sum_y = (-1) * rectangular_coordinates_sum_y;
00168     //cout << "rectangular_coordinates_sum_x: " << rectangular_coordinates_sum_x << endl;
00169     //cout << "rectangular_coordinates_sum_y: " << rectangular_coordinates_sum_y << endl;
00170         //pub the coordinates_sum message.
00171         micros_mars_task_alloc::ForcePtr force_ptr(new micros_mars_task_alloc::Force);
00172     //devided by 12 to avoid the resulted distance being too large
00173     force_ptr -> magnitude = float( sqrt(double(rectangular_coordinates_sum_x * rectangular_coordinates_sum_x) + double(rectangular_coordinates_sum_y * rectangular_coordinates_sum_y))/12.0);
00174         force_ptr -> direction = float( fmod((atan2(double(rectangular_coordinates_sum_y), double(rectangular_coordinates_sum_x)) + 2 * double(pi_)) , (2 * double(pi_))) );
00175         
00176         //cout << "force_ptr -> magnitude: " << force_ptr -> magnitude << endl;
00177         //cout << "force_ptr -> direction: " << force_ptr -> direction << endl;
00178         
00179         pub_ = nh_.advertise<micros_mars_task_alloc::Force>("force", 10);//This topic is a relative topic. Because of getPrivateNodehandle(), nodelet name feelforce will be added as the prefix.
00180         pub_.publish(force_ptr);
00181 }
00182 }//namespace micros_mars_task_alloc
00183 PLUGINLIB_EXPORT_CLASS(micros_mars_task_alloc::Feelforce, nodelet::Nodelet)


micros_mars_task_alloc
Author(s): Minglong Li , Xiaodong Yi , Yanzhen Wang , Zhongxuan Cai
autogenerated on Mon Jul 1 2019 19:55:03