pheeno_robot.cpp
Go to the documentation of this file.
1 #include "ros/ros.h"
2 #include "std_msgs/Float32.h"
3 #include "std_msgs/Int16.h"
4 #include "geometry_msgs/Twist.h"
5 #include "nav_msgs/Odometry.h"
7 #include <vector>
8 #include <complex>
9 #include <cstdlib>
10 #include <iostream>
11 
12 /*
13  * Contructor for the PheenoRobot Class.
14  *
15  * The class constructor fills all std::vector variables with zeros
16  * for use by the setters. Publishers and Subscribers are formally
17  * defined as well.
18  *
19  */
20 PheenoRobot::PheenoRobot(std::string pheeno_name)
21 {
22  ROS_INFO("Creating Pheeno Robot.");
23  pheeno_namespace_id_ = pheeno_name;
24 
25  // Create IR sensor vector upon construction. (6 placements)
26  for (int i = 0; i < 6; i++)
27  {
28  ir_sensor_values_.push_back(0);
29  }
30 
31  // Create sensor vector upon construction. (3 placements)
32  for (int i = 0; i < 3; i++)
33  {
34  odom_pose_position_.push_back(0);
35  odom_twist_linear_.push_back(0);
36  odom_twist_angular_.push_back(0);
37 
38  magnetometer_values_.push_back(0);
39  gyroscope_values_.push_back(0);
40  accelerometer_values_.push_back(0);
41  }
42 
43  // Create sensor vector upon construction. (4 placements)
44  for (int i = 0; i < 4; i++)
45  {
46  odom_pose_orient_.push_back(0);
47  encoder_values_.push_back(0);
48  }
49 
50  // IR Sensor Subscribers
51  sub_ir_center_ = nh_.subscribe(pheeno_name + "/scan_center", 10,
53  sub_ir_right_ = nh_.subscribe(pheeno_name + "/scan_right", 10,
55  sub_ir_left_ = nh_.subscribe(pheeno_name + "/scan_left", 10,
57  sub_ir_cr_ = nh_.subscribe(pheeno_name + "/scan_cr", 10,
59  sub_ir_cl_ = nh_.subscribe(pheeno_name + "/scan_cl", 10,
61  sub_ir_back_ = nh_.subscribe(pheeno_name + "/scan_back", 10,
63  sub_ir_bottom_ = nh_.subscribe(pheeno_name + "/scan_bottom", 10,
65 
66  // Odom Subscriber
67  sub_odom_ = nh_.subscribe(pheeno_name + "/odom", 1,
69 
70  // Encoder Subscribers
71  sub_encoder_LL_ = nh_.subscribe(pheeno_name + "/encoder_LL", 10,
73  sub_encoder_LR_ = nh_.subscribe(pheeno_name + "/encoder_LR", 10,
75  sub_encoder_RL_ = nh_.subscribe(pheeno_name + "/encoder_RL", 10,
77  sub_encoder_RR_ = nh_.subscribe(pheeno_name + "/encoder_RR", 10,
79 
80  // Magnetometer, Gyroscope, Accelerometer Subscriber
81  sub_magnetometer_ = nh_.subscribe(pheeno_name + "/magnetometer", 10,
83  sub_gyroscope_ = nh_.subscribe(pheeno_name + "/gyroscope", 10,
85  sub_accelerometer_ = nh_.subscribe(pheeno_name + "/accelerometer", 10,
87 
88  // cmd_vel Publisher
89  pub_cmd_vel_ = nh_.advertise<geometry_msgs::Twist>(pheeno_name + "/cmd_vel", 100);
90 
91 }
92 
93 /*
94  * Publishes command velocity (cmd_vel) messages.
95  *
96  * The specific Topic name that the message is published to is defined
97  * in the Constructor for the PheenoRobot class.
98  */
99 void PheenoRobot::publish(geometry_msgs::Twist velocity)
100 {
101  pub_cmd_vel_.publish(velocity);
102 }
103 
104 /*
105  * Callback function for the IR Sensor (center) ROS subscriber.
106  */
107 void PheenoRobot::irSensorCenterCallback(const std_msgs::Float32::ConstPtr& msg)
108 {
109  ir_sensor_center_.data = msg->data;
110  ir_sensor_values_[0] = static_cast<double>(msg->data);
111 }
112 
113 /*
114  * Callback function for the IR Sensor (back) ROS subscriber.
115  */
116 void PheenoRobot::irSensorBackCallback(const std_msgs::Float32::ConstPtr& msg)
117 {
118  ir_sensor_back_.data = msg->data;
119  ir_sensor_values_[1] = static_cast<double>(msg->data);
120 }
121 
122 /*
123  * Callback function for the IR Sensor (right) ROS subscriber.
124  */
125 void PheenoRobot::irSensorRightCallback(const std_msgs::Float32::ConstPtr& msg)
126 {
127  ir_sensor_right_.data = msg->data;
128  ir_sensor_values_[2] = static_cast<double>(msg->data);
129 }
130 
131 /*
132  * Callback function for the IR Sensor (left) ROS subscriber.
133  */
134 void PheenoRobot::irSensorLeftCallback(const std_msgs::Float32::ConstPtr& msg)
135 {
136  ir_sensor_left_.data = msg->data;
137  ir_sensor_values_[3] = static_cast<double>(msg->data);
138 }
139 
140 /*
141  * Callback function for the IR Sensor (center-right) ROS subscriber.
142  */
143 void PheenoRobot::irSensorCRightCallback(const std_msgs::Float32::ConstPtr& msg)
144 {
145  ir_sensor_c_right_.data = msg->data;
146  ir_sensor_values_[4] = static_cast<double>(msg->data);
147 }
148 
149 /*
150  * Callback function for the IR Sensor (center-left) ROS subscriber.
151  */
152 void PheenoRobot::irSensorCLeftCallback(const std_msgs::Float32::ConstPtr& msg)
153 {
154  ir_sensor_c_left_.data = msg->data;
155  ir_sensor_values_[5] = static_cast<double>(msg->data);
156 }
157 
158 /*
159  * Given a specific sensor limit, this member function returns a bool if
160  * any of the sensors within ir_sensor_values is triggered.
161  */
162 bool PheenoRobot::irSensorTriggered(float sensor_limit)
163 {
164  int count = 0;
165  for (int i = 0; i < 7; i++)
166  {
167  if (ir_sensor_values_[i] < sensor_limit)
168  {
169  count += 1;
170  }
171  }
172 
173  // Greater than 1 instead of 0, because we aren't using the back IR sensor.
174  return (count > 1) ? true : false;
175 }
176 
177 /*
178  * Callback function for the IR Sensor (bottom) ROS subscriber.
179  *
180  * Sets the data to either 0 or 1 if the message recieved is less than
181  * 1600 or greater than 1600, respectively. The 1600 number is dependent
182  * on the IR sensor used, therefore its value can be changed for use with
183  * different applications.
184  *
185  * NOTE: ONLY FOR THE PHEENO MARKOV CHAIN EXPERIMENT.
186  */
187 void PheenoRobot::irSensorBottomCallback(const std_msgs::Int16::ConstPtr& msg)
188 {
189  if (msg->data < 1600)
190  {
191  ir_sensor_bottom_.data = 0; // Black on the bottom
192  }
193  else
194  {
195  ir_sensor_bottom_.data = 1; // White on the bottom
196  }
197 }
198 
199 /*
200  * Callback function for the odom ROS subscriber.
201  *
202  * This will set message data to odom pose (position and orientation) and twist
203  * (linear and angular) variables.
204  *
205  * NOTE: ONLY USED IF `libgazebo_ros_p3d.so` PLUGIN IS IN THE XACRO FILE.
206  */
207 void PheenoRobot::odomCallback(const nav_msgs::Odometry::ConstPtr& msg)
208 {
209  // Assign values to appropriate pose information.
210  odom_pose_position_[0] = static_cast<double>(msg->pose.pose.position.x);
211  odom_pose_position_[1] = static_cast<double>(msg->pose.pose.position.y);
212  odom_pose_position_[2] = static_cast<double>(msg->pose.pose.position.z);
213  odom_pose_orient_[0] = static_cast<double>(msg->pose.pose.orientation.x);
214  odom_pose_orient_[1] = static_cast<double>(msg->pose.pose.orientation.y);
215  odom_pose_orient_[2] = static_cast<double>(msg->pose.pose.orientation.z);
216  odom_pose_orient_[3] = static_cast<double>(msg->pose.pose.orientation.w);
217 
218  // Assign values to appropriate twist information.
219  odom_twist_linear_[0] = static_cast<double>(msg->twist.twist.linear.x);
220  odom_twist_linear_[1] = static_cast<double>(msg->twist.twist.linear.y);
221  odom_twist_linear_[2] = static_cast<double>(msg->twist.twist.linear.z);
222  odom_twist_angular_[0] = static_cast<double>(msg->twist.twist.angular.x);
223  odom_twist_angular_[1] = static_cast<double>(msg->twist.twist.angular.y);
224  odom_twist_angular_[2] = static_cast<double>(msg->twist.twist.angular.z);
225 }
226 
227 /*
228  * Callback function for the Encoder LL ROS subscriber.
229  */
230 void PheenoRobot::encoderLLCallback(const std_msgs::Int16::ConstPtr& msg)
231 {
232  encoder_values_[0] = static_cast<int>(msg->data);
233 }
234 
235 /*
236  * Callback function for the Encoder LR ROS subscriber.
237  */
238 void PheenoRobot::encoderLRCallback(const std_msgs::Int16::ConstPtr& msg)
239 {
240  encoder_values_[1] = static_cast<int>(msg->data);
241 }
242 
243 /*
244  * Callback function for the Encoder RL ROS subscriber.
245  */
246 void PheenoRobot::encoderRLCallback(const std_msgs::Int16::ConstPtr& msg)
247 {
248  encoder_values_[2] = static_cast<int>(msg->data);
249 }
250 
251 /*
252  * Callback function for the Encoder RR ROS subscriber.
253  */
254 void PheenoRobot::encoderRRCallback(const std_msgs::Int16::ConstPtr& msg)
255 {
256  encoder_values_[3] = static_cast<int>(msg->data);
257 }
258 
259 /*
260  * Callback function for the Magnetometer sensor ROS subscriber.
261  */
262 void PheenoRobot::magnetometerCallback(const geometry_msgs::Vector3::ConstPtr& msg)
263 {
264  magnetometer_values_[0] = static_cast<double>(msg->x);
265  magnetometer_values_[1] = static_cast<double>(msg->y);
266  magnetometer_values_[2] = static_cast<double>(msg->z);
267 }
268 
269 /*
270  * Callback function for the Gyroscope sensor ROS subscriber.
271  */
272 void PheenoRobot::gyroscopeCallback(const geometry_msgs::Vector3::ConstPtr& msg)
273 {
274  gyroscope_values_[0] = static_cast<double>(msg->x);
275  gyroscope_values_[1] = static_cast<double>(msg->y);
276  gyroscope_values_[2] = static_cast<double>(msg->z);
277 }
278 
279 /*
280  * Callback function for the Accelerometer sensor ROS subscriber.
281  */
282 void PheenoRobot::accelerometerCallback(const geometry_msgs::Vector3::ConstPtr& msg)
283 {
284  accelerometer_values_[0] = static_cast<double>(msg->x);
285  accelerometer_values_[1] = static_cast<double>(msg->y);
286  accelerometer_values_[2] = static_cast<double>(msg->z);
287 }
288 
289 /*
290  * Callback function for the Pi Cam ROS subscriber.
291  *
292  * Will recieve sensor_msgs.Image() messages and save only the current frame. If
293  * the user needs to do image manipulation, use the CV_BRIDGE ros package to
294  * convert the sensor_msgs.Image() data type to one useable by OpenCV.
295  */
297 {
298  ROS_INFO("Not in use yet.");
299 }
300 
301 /*
302  * Generates a random turn direction (a sign change) based on a user provided value.
303  */
304 double PheenoRobot::randomTurn(float angular)
305 {
306  return rand() % 10 + 1 <= 5 ? (-1 * angular) : angular;
307 }
308 
309 /*
310  * Obstacle avoidance logic for a robot moving in a linear motion.
311  *
312  * Using class specific IR values, this simple if-else logic progresses by
313  * comparing them to a certain range to avoid (default value). If triggered,
314  * the references to linear and angular are set to specific values to make the
315  * robot avoid the obstacle.
316  */
317 void PheenoRobot::avoidObstaclesLinear(double& linear, double& angular, float angular_velocity, float linear_velocity, double range_to_avoid)
318 {
319  if (ir_sensor_values_[0] < range_to_avoid)
320  {
321  if (std::abs((ir_sensor_values_[2] - ir_sensor_values_[3])) < 5.0 ||
322  (ir_sensor_values_[2] > range_to_avoid && ir_sensor_values_[3] > range_to_avoid))
323  {
324  linear = 0.0;
325  angular = randomTurn();
326  }
327 
329  {
330  linear = 0.0;
331  angular = -1 * angular_velocity; // Turn Left
332  }
333  else
334  {
335  linear = 0.0;
336  angular = angular_velocity; // Turn Right
337  }
338  }
339  else if (ir_sensor_values_[4] < range_to_avoid && ir_sensor_values_[5] < range_to_avoid)
340  {
341  linear = 0.0;
342  angular = randomTurn();
343  }
344  else if (ir_sensor_values_[4] < range_to_avoid)
345  {
346  linear = 0.0;
347  angular = -1 * angular_velocity; // Turn Left
348  }
349  else if (ir_sensor_values_[5] < range_to_avoid)
350  {
351  linear = 0.0;
352  angular = angular_velocity; // Turn Right
353  }
354  else if (ir_sensor_values_[2] < range_to_avoid)
355  {
356  linear = 0.0;
357  angular = -1 * angular_velocity; // Turn Left
358  }
359  else if (ir_sensor_values_[3] < range_to_avoid)
360  {
361  linear = 0.0;
362  angular = angular_velocity; // Turn Right
363  }
364  else
365  {
366  linear = linear_velocity; // Move Straight
367  angular = 0.0;
368  }
369 }
370 
371 /*
372  * Obstacle avoidance logic for a robot moving in an angular (turning) motion.
373  *
374  * Using class specific IR values, this simple if-else logic progresses by
375  * comparing them to a certain range to avoid (default value). If triggered,
376  * the references to angular are set to specific values to make the robot avoid
377  * the obstacle. Compared to the linear version of this callback member
378  * function, this function only modifies the angular reference.
379  */
380 void PheenoRobot::avoidObstaclesAngular(double& angular, double& random_turn_value, float angular_velocity, double range_to_avoid)
381 {
382  if (ir_sensor_values_[0] < range_to_avoid)
383  {
384  if (std::abs((ir_sensor_values_[2] - ir_sensor_values_[3])) < 5.0 ||
385  (ir_sensor_values_[2] > range_to_avoid && ir_sensor_values_[3] > range_to_avoid))
386  {
387  angular = randomTurn();
388  }
389 
391  {
392  angular = -1 * angular_velocity; // Turn Left
393  }
394  else
395  {
396  angular = angular_velocity; // Turn Right
397  }
398  }
399  else if (ir_sensor_values_[4] < range_to_avoid && ir_sensor_values_[5] < range_to_avoid)
400  {
401  angular = randomTurn();
402  }
403  else if (ir_sensor_values_[4] < range_to_avoid)
404  {
405  angular = -1 * angular_velocity; // Turn Left
406  }
407  else if (ir_sensor_values_[5] < range_to_avoid)
408  {
409  angular = angular_velocity; // Turn Right
410  }
411  else if (ir_sensor_values_[2] < range_to_avoid)
412  {
413  angular = -1 * angular_velocity; // Turn Left
414  }
415  else if (ir_sensor_values_[3] < range_to_avoid)
416  {
417  angular = angular_velocity; // Turn Right
418  }
419  else
420  {
421  angular = random_turn_value;
422  }
423 
424  if (angular != random_turn_value)
425  {
426  random_turn_value = angular;
427  }
428 }
bool irSensorTriggered(float sensor_limits)
void irSensorCLeftCallback(const std_msgs::Float32::ConstPtr &msg)
ros::NodeHandle nh_
Definition: pheeno_robot.h:67
void accelerometerCallback(const geometry_msgs::Vector3::ConstPtr &msg)
void publish(geometry_msgs::Twist velocity)
void irSensorBottomCallback(const std_msgs::Int16::ConstPtr &msg)
void gyroscopeCallback(const geometry_msgs::Vector3::ConstPtr &msg)
std::vector< double > gyroscope_values_
Definition: pheeno_robot.h:35
void publish(const boost::shared_ptr< M > &message) const
PheenoRobot(std::string pheeno_name)
ros::Subscriber sub_ir_cr_
Definition: pheeno_robot.h:73
std::vector< double > magnetometer_values_
Definition: pheeno_robot.h:34
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
ros::Subscriber sub_odom_
Definition: pheeno_robot.h:78
void odomCallback(const nav_msgs::Odometry::ConstPtr &msg)
void encoderRLCallback(const std_msgs::Int16::ConstPtr &msg)
void irSensorCenterCallback(const std_msgs::Float32::ConstPtr &msg)
std_msgs::Float32 ir_sensor_back_
Definition: pheeno_robot.h:26
std_msgs::Float32 ir_sensor_center_
Definition: pheeno_robot.h:25
ros::Subscriber sub_gyroscope_
Definition: pheeno_robot.h:84
std::vector< double > odom_pose_position_
Definition: pheeno_robot.h:40
ros::Subscriber sub_encoder_RL_
Definition: pheeno_robot.h:81
ros::Subscriber sub_magnetometer_
Definition: pheeno_robot.h:83
void irSensorBackCallback(const std_msgs::Float32::ConstPtr &msg)
ros::Subscriber sub_ir_left_
Definition: pheeno_robot.h:72
ros::Subscriber sub_encoder_LR_
Definition: pheeno_robot.h:80
std_msgs::Int16 ir_sensor_bottom_
Definition: pheeno_robot.h:31
std_msgs::Float32 ir_sensor_c_right_
Definition: pheeno_robot.h:29
std::vector< double > odom_twist_angular_
Definition: pheeno_robot.h:43
void magnetometerCallback(const geometry_msgs::Vector3::ConstPtr &msg)
ros::Subscriber sub_ir_bottom_
Definition: pheeno_robot.h:76
std::vector< double > odom_pose_orient_
Definition: pheeno_robot.h:41
#define ROS_INFO(...)
std_msgs::Float32 ir_sensor_c_left_
Definition: pheeno_robot.h:30
std_msgs::Float32 ir_sensor_right_
Definition: pheeno_robot.h:27
ros::Subscriber sub_encoder_RR_
Definition: pheeno_robot.h:82
ros::Subscriber sub_ir_center_
Definition: pheeno_robot.h:70
ros::Subscriber sub_ir_right_
Definition: pheeno_robot.h:71
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
std::vector< double > odom_twist_linear_
Definition: pheeno_robot.h:42
ros::Subscriber sub_accelerometer_
Definition: pheeno_robot.h:85
void piCamCallback()
void encoderLRCallback(const std_msgs::Int16::ConstPtr &msg)
ros::Subscriber sub_encoder_LL_
Definition: pheeno_robot.h:79
ros::Publisher pub_cmd_vel_
Definition: pheeno_robot.h:88
void avoidObstaclesAngular(double &angular, double &random_turn_value, float angular_velocity=1.2, double range_to_avoid=20.0)
ros::Subscriber sub_ir_back_
Definition: pheeno_robot.h:75
ros::Subscriber sub_ir_cl_
Definition: pheeno_robot.h:74
void encoderLLCallback(const std_msgs::Int16::ConstPtr &msg)
void encoderRRCallback(const std_msgs::Int16::ConstPtr &msg)
void irSensorLeftCallback(const std_msgs::Float32::ConstPtr &msg)
std::vector< double > ir_sensor_values_
Definition: pheeno_robot.h:32
double randomTurn(float angular=0.06)
void irSensorCRightCallback(const std_msgs::Float32::ConstPtr &msg)
std_msgs::Float32 ir_sensor_left_
Definition: pheeno_robot.h:28
std::vector< int > encoder_values_
Definition: pheeno_robot.h:33
std::vector< double > accelerometer_values_
Definition: pheeno_robot.h:36
std::string pheeno_namespace_id_
Definition: pheeno_robot.h:22
void irSensorRightCallback(const std_msgs::Float32::ConstPtr &msg)
void avoidObstaclesLinear(double &linear, double &angular, float angular_velocity=1.2, float linear_velocity=0.08, double range_to_avoid=20.0)


pheeno_ros_sim
Author(s): Zahi Kakish
autogenerated on Mon Jun 10 2019 14:25:55