Go to the documentation of this file.00001
00010
00011
00012
00013
00014 #ifndef RANDOM_WALKER_CONTROLLER_HPP_
00015 #define RANDOM_WALKER_CONTROLLER_HPP_
00016
00017
00018
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();
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())
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
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
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
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())
00382 {
00383
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);
00390 return;
00391 }
00392
00393 if (change_direction_)
00394 {
00395 change_direction_ = false;
00396
00397
00398 turning_duration_ = ros::Duration(((double)std::rand() / (double)RAND_MAX) * (M_PI / vel_ang_));
00399
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 }
00435 #endif