random_walker_controller.hpp
Go to the documentation of this file.
1 
10 /*****************************************************************************
11 ** Ifdefs
12 *****************************************************************************/
13 
14 #ifndef RANDOM_WALKER_CONTROLLER_HPP_
15 #define RANDOM_WALKER_CONTROLLER_HPP_
16 
17 /*****************************************************************************
18 ** Includes
19 *****************************************************************************/
20 #define _USE_MATH_DEFINES
21 #include <cmath>
22 #include <cstdlib>
23 #include <ctime>
24 #include <geometry_msgs/Twist.h>
25 #include <kobuki_msgs/BumperEvent.h>
26 #include <kobuki_msgs/CliffEvent.h>
27 #include <kobuki_msgs/Led.h>
28 #include <kobuki_msgs/WheelDropEvent.h>
29 #include <ros/ros.h>
30 #include <std_msgs/Empty.h>
32 
33 namespace kobuki
34 {
35 
43 {
44 public:
45  RandomWalkerController(ros::NodeHandle& nh_priv, std::string& name) : Controller(),
46  nh_priv_(nh_priv),
47  name_(name),
48  change_direction_(false),
49  stop_(false),
50  bumper_left_pressed_(false),
52  bumper_right_pressed_(false),
53  cliff_left_detected_(false),
55  cliff_right_detected_(false),
56  led_bumper_on_(false),
57  led_cliff_on_(false),
58  led_wheel_drop_on_(false),
59  turning_(false),
61  {};
63 
68  bool init()
69  {
74  wheel_drop_event_subscriber_ = nh_priv_.subscribe("events/wheel_drop", 10,
76  cmd_vel_publisher_ = nh_priv_.advertise<geometry_msgs::Twist>("commands/velocity", 10);
77  led1_publisher_ = nh_priv_.advertise<kobuki_msgs::Led>("commands/led1", 10);
78  led2_publisher_ = nh_priv_.advertise<kobuki_msgs::Led> ("commands/led2", 10);
79 
80  nh_priv_.param("linear_velocity", vel_lin_, 0.5);
81  nh_priv_.param("angular_velocity", vel_ang_, 0.1);
82  ROS_INFO_STREAM("Velocity parameters: linear velocity = " << vel_lin_
83  << ", angular velocity = " << vel_ang_ << " [" << name_ <<"]");
84  std::srand(std::time(0));
85 
86  this->enable(); // enable controller
87 
88  return true;
89  };
90 
91 
95  void spin();
96 
97 private:
101  std::string name_;
111  bool stop_;
135  double vel_lin_;
137  double vel_ang_;
145  bool turning_;
146 
151  void enableCB(const std_msgs::EmptyConstPtr msg);
152 
157  void disableCB(const std_msgs::EmptyConstPtr msg);
158 
163  void bumperEventCB(const kobuki_msgs::BumperEventConstPtr msg);
164 
169  void cliffEventCB(const kobuki_msgs::CliffEventConstPtr msg);
170 
175  void wheelDropEventCB(const kobuki_msgs::WheelDropEventConstPtr msg);
176 };
177 
178 void RandomWalkerController::enableCB(const std_msgs::EmptyConstPtr msg)
179 {
180  if (this->enable())
181  {
182  ROS_INFO_STREAM("Controller has been enabled. [" << name_ << "]");
183  }
184  else
185  {
186  ROS_INFO_STREAM("Controller was already enabled. [" << name_ <<"]");
187  }
188 };
189 
190 void RandomWalkerController::disableCB(const std_msgs::EmptyConstPtr msg)
191 {
192  if (this->disable())
193  {
194  ROS_INFO_STREAM("Controller has been disabled. [" << name_ <<"]");
195  }
196  else
197  {
198  ROS_INFO_STREAM("Controller was already disabled. [" << name_ <<"]");
199  }
200 };
201 
202 void RandomWalkerController::bumperEventCB(const kobuki_msgs::BumperEventConstPtr msg)
203 {
204  if (this->getState()) // check, if the controller is active
205  {
206  if (msg->state == kobuki_msgs::BumperEvent::PRESSED)
207  {
208  switch (msg->bumper)
209  {
210  case kobuki_msgs::BumperEvent::LEFT:
212  {
213  bumper_left_pressed_ = true;
214  change_direction_ = true;
215  }
216  break;
217  case kobuki_msgs::BumperEvent::CENTER:
219  {
220  bumper_center_pressed_ = true;
221  change_direction_ = true;
222  }
223  break;
224  case kobuki_msgs::BumperEvent::RIGHT:
226  {
227  bumper_right_pressed_ = true;
228  change_direction_ = true;
229  }
230  break;
231  }
232  }
233  else // kobuki_msgs::BumperEvent::RELEASED
234  {
235  switch (msg->bumper)
236  {
237  case kobuki_msgs::BumperEvent::LEFT: bumper_left_pressed_ = false; break;
238  case kobuki_msgs::BumperEvent::CENTER: bumper_center_pressed_ = false; break;
239  case kobuki_msgs::BumperEvent::RIGHT: bumper_right_pressed_ = false; break;
240  }
241  }
243  {
244  kobuki_msgs::LedPtr led_msg_ptr;
245  led_msg_ptr.reset(new kobuki_msgs::Led());
246  led_msg_ptr->value = kobuki_msgs::Led::ORANGE;
247  led1_publisher_.publish(led_msg_ptr);
248  led_bumper_on_ = true;
249  }
251  {
252  kobuki_msgs::LedPtr led_msg_ptr;
253  led_msg_ptr.reset(new kobuki_msgs::Led());
254  led_msg_ptr->value = kobuki_msgs::Led::BLACK;
255  led1_publisher_.publish(led_msg_ptr);
256  led_bumper_on_ = false;
257  }
258  if (change_direction_)
259  {
260  ROS_INFO_STREAM("Bumper pressed. Changing direction. [" << name_ << "]");
261  }
262  }
263 };
264 
265 void RandomWalkerController::cliffEventCB(const kobuki_msgs::CliffEventConstPtr msg)
266 {
267  if (msg->state == kobuki_msgs::CliffEvent::CLIFF)
268  {
269  switch (msg->sensor)
270  {
271  case kobuki_msgs::CliffEvent::LEFT:
273  {
274  cliff_left_detected_ = true;
275  change_direction_ = true;
276  }
277  break;
278  case kobuki_msgs::CliffEvent::CENTER:
280  {
281  cliff_center_detected_ = true;
282  change_direction_ = true;
283  }
284  break;
285  case kobuki_msgs::CliffEvent::RIGHT:
287  {
288  cliff_right_detected_ = true;
289  change_direction_ = true;
290  }
291  break;
292  }
293  }
294  else // kobuki_msgs::BumperEvent::FLOOR
295  {
296  switch (msg->sensor)
297  {
298  case kobuki_msgs::CliffEvent::LEFT: cliff_left_detected_ = false; break;
299  case kobuki_msgs::CliffEvent::CENTER: cliff_center_detected_ = false; break;
300  case kobuki_msgs::CliffEvent::RIGHT: cliff_right_detected_ = false; break;
301  }
302  }
304  {
305  kobuki_msgs::LedPtr led_msg_ptr;
306  led_msg_ptr.reset(new kobuki_msgs::Led());
307  led_msg_ptr->value = kobuki_msgs::Led::ORANGE;
308  led2_publisher_.publish(led_msg_ptr);
309  led_cliff_on_ = true;
310  }
312  {
313  kobuki_msgs::LedPtr led_msg_ptr;
314  led_msg_ptr.reset(new kobuki_msgs::Led());
315  led_msg_ptr->value = kobuki_msgs::Led::BLACK;
316  led2_publisher_.publish(led_msg_ptr);
317  led_cliff_on_ = false;
318  }
319  if (change_direction_)
320  {
321  ROS_INFO_STREAM("Cliff detected. Changing direction. [" << name_ << "]");
322  }
323 };
324 
325 void RandomWalkerController::wheelDropEventCB(const kobuki_msgs::WheelDropEventConstPtr msg)
326 {
327  if (msg->state == kobuki_msgs::WheelDropEvent::DROPPED)
328  {
329  switch (msg->wheel)
330  {
331  case kobuki_msgs::WheelDropEvent::LEFT:
333  {
335  }
336  break;
337  case kobuki_msgs::WheelDropEvent::RIGHT:
339  {
341  }
342  break;
343  }
344  }
345  else // kobuki_msgs::WheelDropEvent::RAISED
346  {
347  switch (msg->wheel)
348  {
349  case kobuki_msgs::WheelDropEvent::LEFT: wheel_drop_left_detected_ = false; break;
350  case kobuki_msgs::WheelDropEvent::RIGHT: wheel_drop_right_detected_ = false; break;
351  }
352  }
354  {
355  kobuki_msgs::LedPtr led_msg_ptr;
356  led_msg_ptr.reset(new kobuki_msgs::Led());
357  led_msg_ptr->value = kobuki_msgs::Led::RED;
358  led1_publisher_.publish(led_msg_ptr);
359  led2_publisher_.publish(led_msg_ptr);
360  stop_ = true;
361  led_wheel_drop_on_ = true;
362  }
364  {
365  kobuki_msgs::LedPtr led_msg_ptr;
366  led_msg_ptr.reset(new kobuki_msgs::Led());
367  led_msg_ptr->value = kobuki_msgs::Led::BLACK;
368  led1_publisher_.publish(led_msg_ptr);
369  led2_publisher_.publish(led_msg_ptr);
370  stop_ = false;
371  led_wheel_drop_on_ = false;
372  }
373  if (change_direction_)
374  {
375  ROS_INFO_STREAM("Wheel(s) dropped. Stopping. [" << name_ << "]");
376  }
377 };
378 
380 {
381  if (this->getState()) // check, if the controller is active
382  {
383  // Velocity commands
384  geometry_msgs::TwistPtr cmd_vel_msg_ptr;
385  cmd_vel_msg_ptr.reset(new geometry_msgs::Twist());
386 
387  if (stop_)
388  {
389  cmd_vel_publisher_.publish(cmd_vel_msg_ptr); // will be all zero when initialised
390  return;
391  }
392 
393  if (change_direction_)
394  {
395  change_direction_ = false;
396  // calculate a random turning angle (-180 ... +180) based on the set angular velocity
397  // time for turning 180 degrees in seconds = M_PI / angular velocity
398  turning_duration_ = ros::Duration(((double)std::rand() / (double)RAND_MAX) * (M_PI / vel_ang_));
399  // randomly chosen turning direction
400  if (((double)std::rand() / (double)RAND_MAX) >= 0.5)
401  {
402  turning_direction_ = 1;
403  }
404  else
405  {
406  turning_direction_ = -1;
407  }
409  turning_ = true;
410  ROS_INFO_STREAM("Will rotate " << turning_direction_ * turning_duration_.toSec() * vel_ang_ / M_PI * 180
411  << " degrees. [" << name_ << "]");
412  }
413 
414  if (turning_)
415  {
417  {
418  cmd_vel_msg_ptr->angular.z = turning_direction_ * vel_ang_;
419  cmd_vel_publisher_.publish(cmd_vel_msg_ptr);
420  }
421  else
422  {
423  turning_ = false;
424  }
425  }
426  else
427  {
428  cmd_vel_msg_ptr->linear.x = vel_lin_;
429  cmd_vel_publisher_.publish(cmd_vel_msg_ptr);
430  }
431  }
432 };
433 
434 } // namespace kobuki
435 #endif /* RANDOM_WALKER_CONTROLLER_HPP_ */
bool cliff_center_detected_
Flag for center cliff sensor&#39;s state.
double vel_ang_
Angular velocity for rotating.
bool led_bumper_on_
Flag for bumper LED&#39;s state.
double vel_lin_
Linear velocity for moving straight.
void cliffEventCB(const kobuki_msgs::CliffEventConstPtr msg)
Trigger direction change and LED blink, when a cliff is detected.
bool led_wheel_drop_on_
Flag for wheel drop sensor LED&#39;s state.
void publish(const boost::shared_ptr< M > &message) const
bool bumper_center_pressed_
Flag for center bumper&#39;s state.
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
void bumperEventCB(const kobuki_msgs::BumperEventConstPtr msg)
Trigger direction change and LED blink, when a bumper is pressed.
void wheelDropEventCB(const kobuki_msgs::WheelDropEventConstPtr msg)
Trigger stopping and LED blink, when a wheel drop is detected.
void disableCB(const std_msgs::EmptyConstPtr msg)
ROS logging output for disabling the controller.
ros::Subscriber bumper_event_subscriber_
Subscribers.
bool cliff_right_detected_
Flag for right cliff sensor&#39;s state.
ros::Time turning_start_
Start time of turning.
bool wheel_drop_right_detected_
Flag for right wheel drop sensor&#39;s state.
bool param(const std::string &param_name, T &param_val, const T &default_val) const
void enableCB(const std_msgs::EmptyConstPtr msg)
ROS logging output for enabling the controller.
int turning_direction_
Randomly chosen turning direction.
ros::Duration turning_duration_
Randomly chosen turning duration.
ros::Publisher cmd_vel_publisher_
Publishers.
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
bool cliff_left_detected_
Flag for left cliff sensor&#39;s state.
#define ROS_INFO_STREAM(args)
bool change_direction_
Flag for changing direction.
ros::NodeHandle nh_priv_
Private ROS handle.
static Time now()
bool wheel_drop_left_detected_
Flag for left wheel drop sensor&#39;s state.
bool led_cliff_on_
Flag for cliff sensor LED&#39;s state.
bool turning_
Flag for turning state.
bool bumper_right_pressed_
Flag for right bumper&#39;s state.
RandomWalkerController(ros::NodeHandle &nh_priv, std::string &name)
bool bumper_left_pressed_
Flag for left bumper&#39;s state.
ros::Subscriber enable_controller_subscriber_
Subscribers.
void spin()
Publishes velocity commands and triggers the LEDs.


kobuki_random_walker
Author(s): Marcus Liebhardt
autogenerated on Mon Jun 10 2019 13:45:06