pioneer3at.cpp
Go to the documentation of this file.
1 // Copyright 1996-2019 Cyberbotics Ltd.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 /*
16  * To run gmapping you should start gmapping:
17  * rosrun gmapping slam_gmapping scan:=/pioneer3at/Sick_LMS_291/laser_scan/layer0 _xmax:=30 _xmin:=-30 _ymax:=30 _ymin:=-30
18  * _delta:=0.2
19  */
20 
21 #include <sensor_msgs/Image.h>
22 #include <sensor_msgs/Imu.h>
23 #include <sensor_msgs/LaserScan.h>
24 #include <sensor_msgs/NavSatFix.h>
25 #include <signal.h>
26 #include <std_msgs/String.h>
28 #include "ros/ros.h"
29 
30 #include <webots_ros/set_float.h>
31 #include <webots_ros/set_int.h>
32 
33 #define TIME_STEP 32
34 #define NMOTORS 4
35 #define MAX_SPEED 6.4
36 #define OBSTACLE_THRESHOLD 0.1
37 #define DECREASE_FACTOR 0.9
38 #define BACK_SLOWDOWN 0.9
39 
41 
42 static std::vector<float> lidarValues;
43 
44 static int controllerCount;
45 static std::vector<std::string> controllerList;
46 
48 webots_ros::set_int timeStepSrv;
49 
50 static const char *motorNames[NMOTORS] = {"front_left_wheel", "front_right_wheel", "back_left_wheel", "back_right_wheel"};
51 
52 static double GPSValues[3] = {0, 0, 0};
53 static double inertialUnitValues[4] = {0, 0, 0, 0};
54 
55 static int lms291Resolution = 0;
56 static int halfResolution = 0;
57 static double maxRange = 0.0;
58 static double rangeThreshold = 0.0;
59 static std::vector<double> braitenbergCoefficients;
61 
62 // gaussian function
63 double gaussian(double x, double mu, double sigma) {
64  return (1.0 / (sigma * sqrt(2.0 * M_PI))) * exp(-((x - mu) * (x - mu)) / (2 * sigma * sigma));
65 }
66 
67 void updateSpeed() {
68  // init dynamic variables
69  double leftObstacle = 0.0, rightObstacle = 0.0, obstacle = 0.0;
70  double speeds[NMOTORS];
71  // apply the braitenberg coefficients on the resulted values of the lms291
72  // near obstacle sensed on the left side
73  for (int i = 0; i < halfResolution; ++i) {
74  if (lidarValues[i] < rangeThreshold) // far obstacles are ignored
75  leftObstacle += braitenbergCoefficients[i] * (1.0 - lidarValues[i] / maxRange);
76  // near obstacle sensed on the right side
77  int j = lms291Resolution - i - 1;
78  if (lidarValues[j] < rangeThreshold)
79  rightObstacle += braitenbergCoefficients[i] * (1.0 - lidarValues[j] / maxRange);
80  }
81  // overall front obstacle
82  obstacle = leftObstacle + rightObstacle;
83  // compute the speed according to the information on
84  // obstacles
85  if (obstacle > OBSTACLE_THRESHOLD) {
86  const double speedFactor = (1.0 - DECREASE_FACTOR * obstacle) * MAX_SPEED / obstacle;
87  speeds[0] = speedFactor * leftObstacle;
88  speeds[1] = speedFactor * rightObstacle;
89  speeds[2] = BACK_SLOWDOWN * speeds[0];
90  speeds[3] = BACK_SLOWDOWN * speeds[1];
91  } else {
92  speeds[0] = MAX_SPEED;
93  speeds[1] = MAX_SPEED;
94  speeds[2] = MAX_SPEED;
95  speeds[3] = MAX_SPEED;
96  }
97  // set speeds
98  for (int i = 0; i < NMOTORS; ++i) {
99  ros::ServiceClient set_velocity_client;
100  webots_ros::set_float set_velocity_srv;
101  set_velocity_client = n->serviceClient<webots_ros::set_float>(std::string("pioneer3at/") + std::string(motorNames[i]) +
102  std::string("/set_velocity"));
103  set_velocity_srv.request.value = speeds[i];
104  set_velocity_client.call(set_velocity_srv);
105  }
106 }
107 
109  static tf::TransformBroadcaster br;
110  tf::Transform transform;
111  transform.setOrigin(tf::Vector3(-GPSValues[2], GPSValues[0], GPSValues[1]));
113  q = q.inverse();
114  transform.setRotation(q);
115  br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "odom", "base_link"));
116  transform.setIdentity();
117  br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "base_link", "pioneer3at/Sick_LMS_291"));
118 }
119 
120 void GPSCallback(const sensor_msgs::NavSatFix::ConstPtr &values) {
121  GPSValues[0] = values->latitude;
122  GPSValues[1] = values->altitude;
123  GPSValues[2] = values->longitude;
125 }
126 
127 void inertialUnitCallback(const sensor_msgs::Imu::ConstPtr &values) {
128  inertialUnitValues[0] = values->orientation.x;
129  inertialUnitValues[1] = values->orientation.y;
130  inertialUnitValues[2] = values->orientation.z;
131  inertialUnitValues[3] = values->orientation.w;
133 }
134 
135 void lidarCallback(const sensor_msgs::LaserScan::ConstPtr &scan) {
136  int scanSize = scan->ranges.size();
137  lidarValues.resize(scanSize);
138  for (int i = 0; i < scanSize; ++i)
139  lidarValues[i] = scan->ranges[i];
140 
141  lms291Resolution = scanSize;
142  halfResolution = scanSize / 2;
143  maxRange = scan->range_max;
144  rangeThreshold = maxRange / 20.0;
147  for (int i = 0; i < lms291Resolution; ++i)
148  braitenbergCoefficients[i] = gaussian(i, halfResolution, lms291Resolution / 5);
150  }
151 
152  updateSpeed();
153 }
154 
155 // catch names of the controllers availables on ROS network
156 void controllerNameCallback(const std_msgs::String::ConstPtr &name) {
157  controllerCount++;
158  controllerList.push_back(name->data);
159  ROS_INFO("Controller #%d: %s.", controllerCount, controllerList.back().c_str());
160 }
161 
162 void quit(int sig) {
163  ROS_INFO("User stopped the 'pioneer3at' node.");
164  timeStepSrv.request.value = 0;
165  timeStepClient.call(timeStepSrv);
166  ros::shutdown();
167  exit(0);
168 }
169 
170 int main(int argc, char **argv) {
171  std::string controllerName;
172  // create a node named 'pioneer3at' on ROS network
173  ros::init(argc, argv, "pioneer3at", ros::init_options::AnonymousName);
174  n = new ros::NodeHandle;
175 
176  signal(SIGINT, quit);
177 
178  // subscribe to the topic model_name to get the list of availables controllers
179  ros::Subscriber nameSub = n->subscribe("model_name", 100, controllerNameCallback);
180  while (controllerCount == 0 || controllerCount < nameSub.getNumPublishers()) {
181  ros::spinOnce();
182  ros::spinOnce();
183  ros::spinOnce();
184  }
185  ros::spinOnce();
186 
187  timeStepClient = n->serviceClient<webots_ros::set_int>("pioneer3at/robot/time_step");
188  timeStepSrv.request.value = TIME_STEP;
189 
190  // if there is more than one controller available, it let the user choose
191  if (controllerCount == 1)
192  controllerName = controllerList[0];
193  else {
194  int wantedController = 0;
195  std::cout << "Choose the # of the controller you want to use:\n";
196  std::cin >> wantedController;
197  if (1 <= wantedController && wantedController <= controllerCount)
198  controllerName = controllerList[wantedController - 1];
199  else {
200  ROS_ERROR("Invalid number for controller choice.");
201  return 1;
202  }
203  }
204  ROS_INFO("Using controller: '%s'", controllerName.c_str());
205  // leave topic once it is not necessary anymore
206  nameSub.shutdown();
207 
208  // init motors
209  for (int i = 0; i < NMOTORS; ++i) {
210  // position
211  ros::ServiceClient set_position_client;
212  webots_ros::set_float set_position_srv;
213  set_position_client = n->serviceClient<webots_ros::set_float>(std::string("pioneer3at/") + std::string(motorNames[i]) +
214  std::string("/set_position"));
215 
216  set_position_srv.request.value = INFINITY;
217  if (set_position_client.call(set_position_srv) && set_position_srv.response.success)
218  ROS_INFO("Position set to INFINITY for motor %s.", motorNames[i]);
219  else
220  ROS_ERROR("Failed to call service set_position on motor %s.", motorNames[i]);
221 
222  // speed
223  ros::ServiceClient set_velocity_client;
224  webots_ros::set_float set_velocity_srv;
225  set_velocity_client = n->serviceClient<webots_ros::set_float>(std::string("pioneer3at/") + std::string(motorNames[i]) +
226  std::string("/set_velocity"));
227 
228  set_velocity_srv.request.value = 0.0;
229  if (set_velocity_client.call(set_velocity_srv) && set_velocity_srv.response.success == 1)
230  ROS_INFO("Velocity set to 0.0 for motor %s.", motorNames[i]);
231  else
232  ROS_ERROR("Failed to call service set_velocity on motor %s.", motorNames[i]);
233  }
234 
235  // enable lidar
236  ros::ServiceClient set_lidar_client;
237  webots_ros::set_int lidar_srv;
238  ros::Subscriber sub_lidar_scan;
239 
240  set_lidar_client = n->serviceClient<webots_ros::set_int>("pioneer3at/Sick_LMS_291/enable");
241  lidar_srv.request.value = TIME_STEP;
242  if (set_lidar_client.call(lidar_srv) && lidar_srv.response.success) {
243  ROS_INFO("Lidar enabled.");
244  sub_lidar_scan = n->subscribe("pioneer3at/Sick_LMS_291/laser_scan/layer0", 10, lidarCallback);
245  ROS_INFO("Topic for lidar initialized.");
246  while (sub_lidar_scan.getNumPublishers() == 0) {
247  }
248  ROS_INFO("Topic for lidar scan connected.");
249  } else {
250  if (!lidar_srv.response.success)
251  ROS_ERROR("Sampling period is not valid.");
252  ROS_ERROR("Failed to enable lidar.");
253  return 1;
254  }
255 
256  // enable gps
257  ros::ServiceClient set_GPS_client;
258  webots_ros::set_int GPS_srv;
259  ros::Subscriber sub_GPS;
260  set_GPS_client = n->serviceClient<webots_ros::set_int>("pioneer3at/gps/enable");
261  GPS_srv.request.value = 32;
262  if (set_GPS_client.call(GPS_srv) && GPS_srv.response.success) {
263  sub_GPS = n->subscribe("pioneer3at/gps/values", 1, GPSCallback);
264  while (sub_GPS.getNumPublishers() == 0) {
265  }
266  ROS_INFO("GPS enabled.");
267  } else {
268  if (!GPS_srv.response.success)
269  ROS_ERROR("Sampling period is not valid.");
270  ROS_ERROR("Failed to enable GPS.");
271  return 1;
272  }
273 
274  // enable inertial unit
275  ros::ServiceClient set_inertial_unit_client;
276  webots_ros::set_int inertial_unit_srv;
277  ros::Subscriber sub_inertial_unit;
278  set_inertial_unit_client = n->serviceClient<webots_ros::set_int>("pioneer3at/inertial_unit/enable");
279  inertial_unit_srv.request.value = 32;
280  if (set_inertial_unit_client.call(inertial_unit_srv) && inertial_unit_srv.response.success) {
281  sub_inertial_unit = n->subscribe("pioneer3at/inertial_unit/roll_pitch_yaw", 1, inertialUnitCallback);
282  while (sub_inertial_unit.getNumPublishers() == 0) {
283  }
284  ROS_INFO("Inertial unit enabled.");
285  } else {
286  if (!inertial_unit_srv.response.success)
287  ROS_ERROR("Sampling period is not valid.");
288  ROS_ERROR("Failed to enable inertial unit.");
289  return 1;
290  }
291 
292  // enable accelerometer
293  ros::ServiceClient set_accelerometer_client;
294  webots_ros::set_int accelerometer_srv;
295  ros::Subscriber sub_accelerometer;
296  set_accelerometer_client = n->serviceClient<webots_ros::set_int>("pioneer3at/accelerometer/enable");
297  accelerometer_srv.request.value = 32;
298  set_accelerometer_client.call(accelerometer_srv);
299  // enable camera
300  ros::ServiceClient set_camera_client;
301  webots_ros::set_int camera_srv;
302  ros::Subscriber sub_camera;
303  set_camera_client = n->serviceClient<webots_ros::set_int>("pioneer3at/camera/enable");
304  camera_srv.request.value = 64;
305  set_camera_client.call(camera_srv);
306  // enable gyro
307  ros::ServiceClient set_gyro_client;
308  webots_ros::set_int gyro_srv;
309  ros::Subscriber sub_gyro;
310  set_gyro_client = n->serviceClient<webots_ros::set_int>("pioneer3at/gyro/enable");
311  gyro_srv.request.value = 32;
312  set_gyro_client.call(gyro_srv);
313 
314  ROS_INFO("You can now start the creation of the map using 'rosrun gmapping slam_gmapping "
315  "scan:=/pioneer3at/Sick_LMS_291/laser_scan/layer0 _xmax:=30 _xmin:=-30 _ymax:=30 _ymin:=-30 _delta:=0.2'.");
316  ROS_INFO("You can now visualize the sensors output in rqt using 'rqt'.");
317 
318  // main loop
319  while (ros::ok()) {
320  if (!timeStepClient.call(timeStepSrv) || !timeStepSrv.response.success) {
321  ROS_ERROR("Failed to call service time_step for next step.");
322  break;
323  }
324  ros::spinOnce();
325  }
326  timeStepSrv.request.value = 0;
327  timeStepClient.call(timeStepSrv);
328 
329  ros::shutdown();
330  return 0;
331 }
void GPSCallback(const sensor_msgs::NavSatFix::ConstPtr &values)
Definition: pioneer3at.cpp:120
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
static int controllerCount
Definition: pioneer3at.cpp:44
TFSIMD_FORCE_INLINE void setRotation(const Quaternion &q)
#define TIME_STEP
Definition: pioneer3at.cpp:33
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
#define MAX_SPEED
Definition: pioneer3at.cpp:35
static int halfResolution
Definition: pioneer3at.cpp:56
static double rangeThreshold
Definition: pioneer3at.cpp:58
void inertialUnitCallback(const sensor_msgs::Imu::ConstPtr &values)
Definition: pioneer3at.cpp:127
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
static std::vector< float > lidarValues
Definition: pioneer3at.cpp:42
void lidarCallback(const sensor_msgs::LaserScan::ConstPtr &scan)
Definition: pioneer3at.cpp:135
bool call(MReq &req, MRes &res)
ros::ServiceClient timeStepClient
Definition: pioneer3at.cpp:47
static std::string controllerName
static int lms291Resolution
Definition: pioneer3at.cpp:55
void setIdentity()
ros::NodeHandle * n
Definition: pioneer3at.cpp:40
#define NMOTORS
Definition: pioneer3at.cpp:34
#define DECREASE_FACTOR
Definition: pioneer3at.cpp:37
webots_ros::set_int timeStepSrv
Definition: pioneer3at.cpp:48
void broadcastTransform()
Definition: pioneer3at.cpp:108
#define OBSTACLE_THRESHOLD
Definition: pioneer3at.cpp:36
#define ROS_INFO(...)
void quit(int sig)
Definition: pioneer3at.cpp:162
uint32_t getNumPublishers() const
ROSCPP_DECL bool ok()
int main(int argc, char **argv)
Definition: pioneer3at.cpp:170
void sendTransform(const StampedTransform &transform)
void updateSpeed()
Definition: pioneer3at.cpp:67
void controllerNameCallback(const std_msgs::String::ConstPtr &name)
Definition: pioneer3at.cpp:156
static bool areBraitenbergCoefficientsinitialized
Definition: pioneer3at.cpp:60
double gaussian(double x, double mu, double sigma)
Definition: pioneer3at.cpp:63
Quaternion inverse() const
static std::vector< std::string > controllerList
Definition: pioneer3at.cpp:45
static const char * motorNames[NMOTORS]
Definition: pioneer3at.cpp:50
static Time now()
static double GPSValues[3]
Definition: pioneer3at.cpp:52
ROSCPP_DECL void shutdown()
ROSCPP_DECL void spinOnce()
static double maxRange
Definition: pioneer3at.cpp:57
#define ROS_ERROR(...)
static double inertialUnitValues[4]
Definition: pioneer3at.cpp:53
TFSIMD_FORCE_INLINE void setOrigin(const Vector3 &origin)
#define BACK_SLOWDOWN
Definition: pioneer3at.cpp:38
static std::vector< double > braitenbergCoefficients
Definition: pioneer3at.cpp:59


webots_ros
Author(s):
autogenerated on Mon Jul 8 2019 03:19:27