random_walker_controller.hpp
Go to the documentation of this file.
00001 
00010 /*****************************************************************************
00011 ** Ifdefs
00012 *****************************************************************************/
00013 
00014 #ifndef RANDOM_WALKER_CONTROLLER_HPP_
00015 #define RANDOM_WALKER_CONTROLLER_HPP_
00016 
00017 /*****************************************************************************
00018 ** Includes
00019 *****************************************************************************/
00020 #define _USE_MATH_DEFINES
00021 #include <cmath>
00022 #include <cstdlib>
00023 #include <ctime>
00024 #include <geometry_msgs/Twist.h>
00025 #include <kobuki_msgs/BumperEvent.h>
00026 #include <kobuki_msgs/CliffEvent.h>
00027 #include <kobuki_msgs/Led.h>
00028 #include <kobuki_msgs/WheelDropEvent.h>
00029 #include <ros/ros.h>
00030 #include <std_msgs/Empty.h>
00031 #include <yocs_controllers/default_controller.hpp>
00032 
00033 namespace kobuki
00034 {
00035 
00042 class RandomWalkerController : public yocs::Controller
00043 {
00044 public:
00045   RandomWalkerController(ros::NodeHandle& nh_priv, std::string& name) : Controller(),
00046                                                                            nh_priv_(nh_priv),
00047                                                                            name_(name),
00048                                                                            change_direction_(false),
00049                                                                            stop_(false),
00050                                                                            bumper_left_pressed_(false),
00051                                                                            bumper_center_pressed_(false),
00052                                                                            bumper_right_pressed_(false),
00053                                                                            cliff_left_detected_(false),
00054                                                                            cliff_center_detected_(false),
00055                                                                            cliff_right_detected_(false),
00056                                                                            led_bumper_on_(false),
00057                                                                            led_cliff_on_(false),
00058                                                                            led_wheel_drop_on_(false),
00059                                                                            turning_(false),
00060                                                                            turning_direction_(1)
00061                                                                            {};
00062   ~RandomWalkerController(){};
00063 
00068   bool init()
00069   {
00070     enable_controller_subscriber_ = nh_priv_.subscribe("enable", 10, &RandomWalkerController::enableCB, this);
00071     disable_controller_subscriber_ = nh_priv_.subscribe("disable", 10, &RandomWalkerController::disableCB, this);
00072     bumper_event_subscriber_ = nh_priv_.subscribe("events/bumper", 10, &RandomWalkerController::bumperEventCB, this);
00073     cliff_event_subscriber_ = nh_priv_.subscribe("events/cliff", 10, &RandomWalkerController::cliffEventCB, this);
00074     wheel_drop_event_subscriber_ = nh_priv_.subscribe("events/wheel_drop", 10,
00075                                                       &RandomWalkerController::wheelDropEventCB, this);
00076     cmd_vel_publisher_ = nh_priv_.advertise<geometry_msgs::Twist>("commands/velocity", 10);
00077     led1_publisher_ = nh_priv_.advertise<kobuki_msgs::Led>("commands/led1", 10);
00078     led2_publisher_ = nh_priv_.advertise<kobuki_msgs::Led> ("commands/led2", 10);
00079 
00080     nh_priv_.param("linear_velocity", vel_lin_, 0.5);
00081     nh_priv_.param("angular_velocity", vel_ang_, 0.1);
00082     ROS_INFO_STREAM("Velocity parameters: linear velocity = " << vel_lin_
00083                     << ", angular velocity = " << vel_ang_ << " [" << name_ <<"]");
00084     std::srand(std::time(0));
00085 
00086     this->enable(); // enable controller
00087 
00088     return true;
00089   };
00090 
00091 
00095   void spin();
00096 
00097 private:
00099   ros::NodeHandle nh_priv_;
00101   std::string name_;
00103   ros::Subscriber enable_controller_subscriber_, disable_controller_subscriber_;
00105   ros::Subscriber bumper_event_subscriber_, cliff_event_subscriber_, wheel_drop_event_subscriber_;
00107   ros::Publisher cmd_vel_publisher_, led1_publisher_, led2_publisher_;
00109   bool change_direction_;
00111   bool stop_;
00113   bool bumper_left_pressed_;
00115   bool bumper_center_pressed_;
00117   bool bumper_right_pressed_;
00119   bool cliff_left_detected_;
00121   bool cliff_center_detected_;
00123   bool cliff_right_detected_;
00125   bool wheel_drop_left_detected_;
00127   bool wheel_drop_right_detected_;
00129   bool led_bumper_on_;
00131   bool led_cliff_on_;
00133   bool led_wheel_drop_on_;
00135   double vel_lin_;
00137   double vel_ang_;
00139   ros::Duration turning_duration_;
00141   int turning_direction_;
00143   ros::Time turning_start_;
00145   bool turning_;
00146 
00151   void enableCB(const std_msgs::EmptyConstPtr msg);
00152 
00157   void disableCB(const std_msgs::EmptyConstPtr msg);
00158 
00163   void bumperEventCB(const kobuki_msgs::BumperEventConstPtr msg);
00164 
00169   void cliffEventCB(const kobuki_msgs::CliffEventConstPtr msg);
00170 
00175   void wheelDropEventCB(const kobuki_msgs::WheelDropEventConstPtr msg);
00176 };
00177 
00178 void RandomWalkerController::enableCB(const std_msgs::EmptyConstPtr msg)
00179 {
00180   if (this->enable())
00181   {
00182     ROS_INFO_STREAM("Controller has been enabled. [" << name_ << "]");
00183   }
00184   else
00185   {
00186     ROS_INFO_STREAM("Controller was already enabled. [" << name_ <<"]");
00187   }
00188 };
00189 
00190 void RandomWalkerController::disableCB(const std_msgs::EmptyConstPtr msg)
00191 {
00192   if (this->disable())
00193   {
00194     ROS_INFO_STREAM("Controller has been disabled. [" << name_ <<"]");
00195   }
00196   else
00197   {
00198     ROS_INFO_STREAM("Controller was already disabled. [" << name_ <<"]");
00199   }
00200 };
00201 
00202 void RandomWalkerController::bumperEventCB(const kobuki_msgs::BumperEventConstPtr msg)
00203 {
00204   if (this->getState()) // check, if the controller is active
00205   {
00206     if (msg->state == kobuki_msgs::BumperEvent::PRESSED)
00207     {
00208       switch (msg->bumper)
00209       {
00210         case kobuki_msgs::BumperEvent::LEFT:
00211           if (!bumper_left_pressed_)
00212           {
00213             bumper_left_pressed_ = true;
00214             change_direction_ = true;
00215           }
00216           break;
00217         case kobuki_msgs::BumperEvent::CENTER:
00218           if (!bumper_center_pressed_)
00219           {
00220             bumper_center_pressed_ = true;
00221             change_direction_ = true;
00222           }
00223           break;
00224         case kobuki_msgs::BumperEvent::RIGHT:
00225           if (!bumper_right_pressed_)
00226           {
00227             bumper_right_pressed_ = true;
00228             change_direction_ = true;
00229           }
00230           break;
00231       }
00232     }
00233     else // kobuki_msgs::BumperEvent::RELEASED
00234     {
00235       switch (msg->bumper)
00236       {
00237         case kobuki_msgs::BumperEvent::LEFT:    bumper_left_pressed_   = false; break;
00238         case kobuki_msgs::BumperEvent::CENTER:  bumper_center_pressed_ = false; break;
00239         case kobuki_msgs::BumperEvent::RIGHT:   bumper_right_pressed_  = false; break;
00240       }
00241     }
00242     if (!led_bumper_on_ && (bumper_left_pressed_ || bumper_center_pressed_ || bumper_right_pressed_))
00243     {
00244       kobuki_msgs::LedPtr led_msg_ptr;
00245       led_msg_ptr.reset(new kobuki_msgs::Led());
00246       led_msg_ptr->value = kobuki_msgs::Led::ORANGE;
00247       led1_publisher_.publish(led_msg_ptr);
00248       led_bumper_on_ = true;
00249     }
00250     else if (led_bumper_on_ && (!bumper_left_pressed_ && !bumper_center_pressed_ && !bumper_right_pressed_))
00251     {
00252       kobuki_msgs::LedPtr led_msg_ptr;
00253       led_msg_ptr.reset(new kobuki_msgs::Led());
00254       led_msg_ptr->value = kobuki_msgs::Led::BLACK;
00255       led1_publisher_.publish(led_msg_ptr);
00256       led_bumper_on_ = false;
00257     }
00258     if (change_direction_)
00259     {
00260       ROS_INFO_STREAM("Bumper pressed. Changing direction. [" << name_ << "]");
00261     }
00262   }
00263 };
00264 
00265 void RandomWalkerController::cliffEventCB(const kobuki_msgs::CliffEventConstPtr msg)
00266 {
00267   if (msg->state == kobuki_msgs::CliffEvent::CLIFF)
00268   {
00269     switch (msg->sensor)
00270     {
00271       case kobuki_msgs::CliffEvent::LEFT:
00272         if (!cliff_left_detected_)
00273         {
00274           cliff_left_detected_ = true;
00275           change_direction_ = true;
00276         }
00277         break;
00278       case kobuki_msgs::CliffEvent::CENTER:
00279         if (!cliff_center_detected_)
00280         {
00281           cliff_center_detected_ = true;
00282           change_direction_ = true;
00283         }
00284         break;
00285       case kobuki_msgs::CliffEvent::RIGHT:
00286         if (!cliff_right_detected_)
00287         {
00288           cliff_right_detected_ = true;
00289           change_direction_ = true;
00290         }
00291         break;
00292     }
00293   }
00294   else // kobuki_msgs::BumperEvent::FLOOR
00295   {
00296     switch (msg->sensor)
00297     {
00298       case kobuki_msgs::CliffEvent::LEFT:    cliff_left_detected_   = false; break;
00299       case kobuki_msgs::CliffEvent::CENTER:  cliff_center_detected_ = false; break;
00300       case kobuki_msgs::CliffEvent::RIGHT:   cliff_right_detected_  = false; break;
00301     }
00302   }
00303   if (!led_cliff_on_ && (cliff_left_detected_ || cliff_center_detected_ || cliff_right_detected_))
00304   {
00305     kobuki_msgs::LedPtr led_msg_ptr;
00306     led_msg_ptr.reset(new kobuki_msgs::Led());
00307     led_msg_ptr->value = kobuki_msgs::Led::ORANGE;
00308     led2_publisher_.publish(led_msg_ptr);
00309     led_cliff_on_ = true;
00310   }
00311   else if (led_cliff_on_ && (!cliff_left_detected_ && !cliff_center_detected_ && !cliff_right_detected_))
00312   {
00313     kobuki_msgs::LedPtr led_msg_ptr;
00314     led_msg_ptr.reset(new kobuki_msgs::Led());
00315     led_msg_ptr->value = kobuki_msgs::Led::BLACK;
00316     led2_publisher_.publish(led_msg_ptr);
00317     led_cliff_on_ = false;
00318   }
00319   if (change_direction_)
00320   {
00321     ROS_INFO_STREAM("Cliff detected. Changing direction. [" << name_ << "]");
00322   }
00323 };
00324 
00325 void RandomWalkerController::wheelDropEventCB(const kobuki_msgs::WheelDropEventConstPtr msg)
00326 {
00327   if (msg->state == kobuki_msgs::WheelDropEvent::DROPPED)
00328   {
00329     switch (msg->wheel)
00330     {
00331       case kobuki_msgs::WheelDropEvent::LEFT:
00332         if (!wheel_drop_left_detected_)
00333         {
00334           wheel_drop_left_detected_ = true;
00335         }
00336         break;
00337       case kobuki_msgs::WheelDropEvent::RIGHT:
00338         if (!wheel_drop_right_detected_)
00339         {
00340           wheel_drop_right_detected_ = true;
00341         }
00342         break;
00343     }
00344   }
00345   else // kobuki_msgs::WheelDropEvent::RAISED
00346   {
00347     switch (msg->wheel)
00348     {
00349       case kobuki_msgs::WheelDropEvent::LEFT:    wheel_drop_left_detected_   = false; break;
00350       case kobuki_msgs::WheelDropEvent::RIGHT:   wheel_drop_right_detected_  = false; break;
00351     }
00352   }
00353   if (!led_wheel_drop_on_ && (wheel_drop_left_detected_ || wheel_drop_right_detected_))
00354   {
00355     kobuki_msgs::LedPtr led_msg_ptr;
00356     led_msg_ptr.reset(new kobuki_msgs::Led());
00357     led_msg_ptr->value = kobuki_msgs::Led::RED;
00358     led1_publisher_.publish(led_msg_ptr);
00359     led2_publisher_.publish(led_msg_ptr);
00360     stop_ = true;
00361     led_wheel_drop_on_ = true;
00362   }
00363   else if (led_wheel_drop_on_ && (!wheel_drop_left_detected_ && !wheel_drop_right_detected_))
00364   {
00365     kobuki_msgs::LedPtr led_msg_ptr;
00366     led_msg_ptr.reset(new kobuki_msgs::Led());
00367     led_msg_ptr->value = kobuki_msgs::Led::BLACK;
00368     led1_publisher_.publish(led_msg_ptr);
00369     led2_publisher_.publish(led_msg_ptr);
00370     stop_ = false;
00371     led_wheel_drop_on_ = false;
00372   }
00373   if (change_direction_)
00374   {
00375     ROS_INFO_STREAM("Wheel(s) dropped. Stopping. [" << name_ << "]");
00376   }
00377 };
00378 
00379 void RandomWalkerController::spin()
00380 {
00381   if (this->getState()) // check, if the controller is active
00382   {
00383     // Velocity commands
00384     geometry_msgs::TwistPtr cmd_vel_msg_ptr;
00385     cmd_vel_msg_ptr.reset(new geometry_msgs::Twist());
00386 
00387     if (stop_)
00388     {
00389       cmd_vel_publisher_.publish(cmd_vel_msg_ptr); // will be all zero when initialised
00390       return;
00391     }
00392 
00393     if (change_direction_)
00394     {
00395       change_direction_ = false;
00396       // calculate a random turning angle (-180 ... +180) based on the set angular velocity
00397       // time for turning 180 degrees in seconds = M_PI / angular velocity
00398       turning_duration_ = ros::Duration(((double)std::rand() / (double)RAND_MAX) * (M_PI / vel_ang_));
00399       // randomly chosen turning direction
00400       if (((double)std::rand() / (double)RAND_MAX) >= 0.5)
00401       {
00402         turning_direction_ = 1;
00403       }
00404       else
00405       {
00406         turning_direction_ = -1;
00407       }
00408       turning_start_ = ros::Time::now();
00409       turning_ = true;
00410       ROS_INFO_STREAM("Will rotate " << turning_direction_ * turning_duration_.toSec() * vel_ang_ / M_PI * 180
00411                       << " degrees. [" << name_ << "]");
00412     }
00413 
00414     if (turning_)
00415     {
00416       if ((ros::Time::now() - turning_start_) < turning_duration_)
00417       {
00418         cmd_vel_msg_ptr->angular.z = turning_direction_ * vel_ang_;
00419         cmd_vel_publisher_.publish(cmd_vel_msg_ptr);
00420       }
00421       else
00422       {
00423         turning_ = false;
00424       }
00425     }
00426     else
00427     {
00428       cmd_vel_msg_ptr->linear.x = vel_lin_;
00429       cmd_vel_publisher_.publish(cmd_vel_msg_ptr);
00430     }
00431   }
00432 };
00433 
00434 } // namespace kobuki
00435 #endif /* RANDOM_WALKER_CONTROLLER_HPP_ */


kobuki_random_walker
Author(s): Marcus Liebhardt
autogenerated on Wed Sep 16 2015 04:35:24