emc_system
communication.cpp
Go to the documentation of this file.
1 #include "emc/communication.h"
2 
3 #include <ros/node_handle.h>
4 #include <ros/subscribe_options.h>
5 #include <tf2/LinearMath/Transform.h>
6 #include <tf2_geometry_msgs/tf2_geometry_msgs.h>
7 #include <tf2/LinearMath/Quaternion.h>
8 #include <tf2/LinearMath/Matrix3x3.h>
9 
10 #include <geometry_msgs/Twist.h>
11 #include <std_msgs/Empty.h>
12 #include <std_msgs/String.h>
13 #include <string>
14 
15 namespace emc
16 {
17 
18 // ----------------------------------------------------------------------------------------------------
19 
21 {
22 
23  ros::VP_string args;
24  ros::init(args, "emc_system", ros::init_options::AnonymousName);
25  ros::Time::init();
26 
27  ros::NodeHandle nh;
28  std::string laser_param, pose_param, odom_param, bumper_f_param, bumper_b_param, base_ref_param, open_door_param, speak_param, play_param;
29  if (!nh.getParam("laser_", laser_param)) {ROS_ERROR_STREAM("Parameter " << "laser_" << " not set");};
30  if (!nh.getParam("pose_", pose_param)) {ROS_ERROR_STREAM("Parameter " << "pose_" << " not set");};
31  if (!nh.getParam("odom_", odom_param)) {ROS_ERROR_STREAM("Parameter " << "odom_" << " not set");};
32  if (!nh.getParam("bumper_f_", bumper_f_param)) {ROS_ERROR_STREAM("Parameter " << "bumper_f_" << " not set");};
33  if (!nh.getParam("bumper_b_", bumper_b_param)) {ROS_ERROR_STREAM("Parameter " << "bumper_b_" << " not set");};
34  if (!nh.getParam("base_ref_", base_ref_param)) {ROS_ERROR_STREAM("Parameter " << "base_ref_" << " not set");};
35  if (!nh.getParam("open_door_", open_door_param)) {ROS_ERROR_STREAM("Parameter " << "open_door_" << " not set");};
36  if (!nh.getParam("speak_", speak_param)) {ROS_ERROR_STREAM("Parameter " << "speak_" << " not set");};
37  if (!nh.getParam("play_", play_param)) {ROS_ERROR_STREAM("Parameter " << "play_" << " not set");};
38  if (!nh.getParam("base_link_", robot_frame_name)) {ROS_ERROR_STREAM("Parameter " << "base_link_" << " not set");};
39 
40  ros::SubscribeOptions laser_sub_options = ros::SubscribeOptions::create<sensor_msgs::LaserScan>(laser_param, 1, boost::bind(&Communication::laserCallback, this, _1), ros::VoidPtr(), &laser_cb_queue_);
41  sub_laser_ = nh.subscribe(laser_sub_options);
42 
43  ros::SubscribeOptions pose_sub_options = ros::SubscribeOptions::create<geometry_msgs::PoseStamped>(pose_param, 1, boost::bind(&Communication::poseCallback, this, _1), ros::VoidPtr(), &pose_cb_queue_);
44  sub_pose_ = nh.subscribe(pose_sub_options);
45 
46  ros::SubscribeOptions odom_sub_options = ros::SubscribeOptions::create<nav_msgs::Odometry>(odom_param, 1, boost::bind(&Communication::odomCallback, this, _1), ros::VoidPtr(), &odom_cb_queue_);
47  sub_odom_ = nh.subscribe(odom_sub_options);
48 
49  ros::SubscribeOptions bumper_f_sub_options = ros::SubscribeOptions::create<std_msgs::Bool>(bumper_f_param, 1, boost::bind(&Communication::bumperfCallback, this, _1), ros::VoidPtr(), &bumper_f_cb_queue_);
50  sub_bumper_f_ = nh.subscribe(bumper_f_sub_options);
51 
52  ros::SubscribeOptions bumper_b_sub_options = ros::SubscribeOptions::create<std_msgs::Bool>(bumper_b_param, 1, boost::bind(&Communication::bumperbCallback, this, _1), ros::VoidPtr(), &bumper_b_cb_queue_);
53  sub_bumper_b_ = nh.subscribe(bumper_b_sub_options);
54 
55  pub_base_ref_ = nh.advertise<geometry_msgs::Twist>(base_ref_param, 1);
56 
57  pub_open_door_ = nh.advertise<std_msgs::Empty>(open_door_param, 1);
58 
59  pub_speak_ = nh.advertise<std_msgs::String>(speak_param, 1);
60  pub_play_ = nh.advertise<std_msgs::String>(play_param, 1);
61 
62  pub_marker_ = nh.advertise<visualization_msgs::Marker>("/marker", 1);
63 
64  pub_tf2 = std::unique_ptr<tf2_ros::TransformBroadcaster>(new tf2_ros::TransformBroadcaster);
65 
66 
67  // publishers used to visualize information in the localization exercises (particle filter):
68  localization_visualization_pub_laser_msg_ = nh.advertise<sensor_msgs::LaserScan>("/laser_match", 1);
69  localization_visualization_pub_particle_ = nh.advertise<geometry_msgs::PoseArray>("/particles", 1);
70  localization_visualization_pub_pose_ = nh.advertise<geometry_msgs::PoseArray>("/pose_estimate", 1);
71 }
72 
73 // ----------------------------------------------------------------------------------------------------
74 
76 {
77 
78 }
79 
80 // ----------------------------------------------------------------------------------------------------
81 
83 {
84 }
85 
86 // ----------------------------------------------------------------------------------------------------
87 
89 {
90  laser_msg_.reset();
91  laser_cb_queue_.callAvailable();
92 
93  if (!laser_msg_)
94  return false;
95 
96  scan.range_min = laser_msg_->range_min;
97  scan.range_max = laser_msg_->range_max;
98  scan.ranges = laser_msg_->ranges;
99  scan.angle_min = laser_msg_->angle_min;
100  scan.angle_max = laser_msg_->angle_max;
101  scan.angle_increment = laser_msg_->angle_increment;
102  scan.timestamp = laser_msg_->header.stamp.toSec();
103 
104  return true;
105 }
106 
107 // ----------------------------------------------------------------------------------------------------
108 
110 {
111  pose_msg_.reset();
112  pose_cb_queue_.callAvailable();
113 
114  if (!pose_msg_)
115  return false;
116 
117  // Store position. Optitrack swaps the y and z axis,
118  // but to use the convention of rviz, we swap them back
119  pose.x = pose_msg_->pose.position.x;
120  pose.y = pose_msg_->pose.position.z;
121  pose.z = pose_msg_->pose.position.y;
122 
123  // Convert quaternion to roll, pitch, yaw
124  // Again, y and z are swapped to match rviz
125  tf2::Quaternion q(pose_msg_->pose.orientation.x,
126  pose_msg_->pose.orientation.y,
127  pose_msg_->pose.orientation.z,
128  pose_msg_->pose.orientation.w);
129 
130  tf2::Matrix3x3 T(q);
131 
132  double roll, pitch, yaw;
133  T.getRPY(roll, pitch, yaw);
134 
135  // Store orientation
136  pose.roll = roll;
137  pose.pitch = pitch;
138  pose.yaw = yaw;
139 
140  return true;
141 }
142 
143 // ----------------------------------------------------------------------------------------------------
144 
146 {
147  odom_msg_.reset();
148  odom_cb_queue_.callAvailable();
149 
150  if (!odom_msg_)
151  return false;
152 
153  odom.x = odom_msg_->pose.pose.position.x;
154  odom.y = odom_msg_->pose.pose.position.y;
155 
156  // Calculate yaw rotation from quaternion
157  const geometry_msgs::Quaternion& q = odom_msg_->pose.pose.orientation;
158  odom.a = atan2(2 * (q.w * q.z + q.x * q.y), 1 - 2 * (q.y * q.y + q.z * q.z));
159 
160  odom.timestamp = odom_msg_->header.stamp.toSec();
161 
162  return true;
163 }
164 
165 // ----------------------------------------------------------------------------------------------------
166 
168 {
169  bumper_f_msg_.reset();
170 
171  bumper_f_cb_queue_.callAvailable();
172 
173  if (!bumper_f_msg_)
174  return false;
175 
176  bumper.contact = bumper_f_msg_->data;
177  return true;
178 }
179 
180 // ----------------------------------------------------------------------------------------------------
181 
183 {
184  bumper_b_msg_.reset();
185 
186  bumper_b_cb_queue_.callAvailable();
187 
188  if (!bumper_b_msg_)
189  return false;
190 
191  bumper.contact = bumper_b_msg_->data;
192  return true;
193 }
194 
195 // ----------------------------------------------------------------------------------------------------
196 
197 void Communication::sendBaseVelocity(double vx, double vy, double va)
198 {
199  geometry_msgs::Twist ref;
200  ref.linear.x = vx;
201  ref.linear.y = vy;
202  ref.angular.z = va;
203 
204  pub_base_ref_.publish(ref);
205 }
206 
207 // ----------------------------------------------------------------------------------------------------
208 
210 {
211  std_msgs::Empty msg;
212  pub_open_door_.publish(msg);
213 }
214 
215 // ----------------------------------------------------------------------------------------------------
216 
217 void Communication::sendMarker(visualization_msgs::Marker marker)
218 {
219  pub_marker_.publish(marker);
220 }
221 
222 // ----------------------------------------------------------------------------------------------------
223 
225 {
226  std_msgs::String str;
227  str.data = text;
228  pub_speak_.publish(str);
229 }
230 
232 {
233  std_msgs::String str;
234  str.data = file;
235  pub_play_.publish(str);
236 }
237 
238 void Communication::sendPoseEstimate(const geometry_msgs::Transform& pose)
239 {
240  // invert the pose because ros architecture sucks balls
241  tf2::Transform transform;
242  tf2::fromMsg(pose, transform);
243  geometry_msgs::Transform inverted_transform_msg;
244  inverted_transform_msg = tf2::toMsg(transform.inverse());
245 
246  // Publish tf transform
247  geometry_msgs::TransformStamped transformStamped;
248  transformStamped.header.stamp = ros::Time::now();
249  transformStamped.header.frame_id = robot_frame_name;
250  transformStamped.child_frame_id = "map";
251  transformStamped.transform = inverted_transform_msg;
252  pub_tf2->sendTransform(transformStamped);
253 }
254 
255 // ----------------------------------------------------------------------------------------------------
256 
257 void Communication::laserCallback(const sensor_msgs::LaserScanConstPtr& msg)
258 {
259  laser_msg_ = msg;
260 }
261 
262 // ----------------------------------------------------------------------------------------------------
263 
264 void Communication::poseCallback(const geometry_msgs::PoseStampedConstPtr& msg)
265 {
266  pose_msg_ = msg;
267 }
268 
269 // ----------------------------------------------------------------------------------------------------
270 
271 void Communication::odomCallback(const nav_msgs::OdometryConstPtr& msg)
272 {
273  odom_msg_ = msg;
274 }
275 
276 // ----------------------------------------------------------------------------------------------------
277 
278 void Communication::bumperfCallback(const std_msgs::BoolConstPtr& msg)
279 {
280  bumper_f_msg_ = msg;
281 }
282 
283 // ----------------------------------------------------------------------------------------------------
284 
285 void Communication::bumperbCallback(const std_msgs::BoolConstPtr& msg)
286 {
287  bumper_b_msg_ = msg;
288 }
289 
290 // ----------------------------------------------------------------------------------------------------
291 // publishing functions used to visualize information in the localization exercises (particle filter):
292 
293 void Communication::localization_viz_send_laser_scan(double angle_min, double angle_max, double angle_inc, int subsample, std::vector<float> prediction)
294 {
295  sensor_msgs::LaserScan msg{};
296 
297  msg.angle_min = angle_min;
298  msg.angle_max = angle_max;
299  msg.angle_increment = angle_inc * subsample;
300 
301  msg.range_min = 0.01;
302  msg.range_max = 10;
303 
304  msg.header.frame_id = "robot_pose";
305  msg.header.stamp = ros::Time::now();
306 
307  msg.ranges = prediction;
308 
309  this->localization_visualization_pub_laser_msg_.publish(msg); //make correct publisher
310  // pub_node_->send_laser_scan(angle_min, angle_max, angle_inc, subsample, prediction);
311 }
312 
313 void Communication::localization_viz_send_particles(int N, std::vector<std::vector<double>> particle_poses, double mapOrientation)
314 {
315  geometry_msgs::PoseArray msg{};
316 
317  msg.header.frame_id = "map";
318  msg.header.stamp = ros::Time::now();
319  tf2::Quaternion a;
320  msg.poses.reserve(N);
321  for (int i = 0; i < N; i++)
322  {
323  geometry_msgs::Pose posemsg;
324  auto pose_i = particle_poses[i];
325 
326  posemsg.position.x = std::cos(mapOrientation) * pose_i[0] - std::sin(mapOrientation) * pose_i[1];
327  posemsg.position.y = std::sin(mapOrientation) * pose_i[0] + std::cos(mapOrientation) * pose_i[1];
328  posemsg.position.z = 0;
329 
330  a.setRPY(0, 0, pose_i[2] - mapOrientation);
331  posemsg.orientation.w = a.getW();
332  posemsg.orientation.x = a.getX();
333  posemsg.orientation.y = a.getY();
334  posemsg.orientation.z = a.getZ();
335 
336  msg.poses.push_back(posemsg);
337  }
338 
339  this->localization_visualization_pub_particle_.publish(msg);
340 }
341 
343 {
344  geometry_msgs::PoseArray msg;
345 
346  msg.header.frame_id = "map";
347  msg.header.stamp = ros::Time::now();
348  tf2::Quaternion a;
349 
350  msg.poses.reserve(1);
351 
352  geometry_msgs::Pose posemsg;
353  posemsg.position.x = std::cos(mapOrientation) * pose[0] - std::sin(mapOrientation) * pose[1];
354  posemsg.position.y = std::sin(mapOrientation) * pose[0] + std::cos(mapOrientation) * pose[1];
355  posemsg.position.z = 0;
356 
357  a.setRPY(0, 0, pose[2] - mapOrientation);
358  posemsg.orientation.w = a.getW();
359  posemsg.orientation.x = a.getX();
360  posemsg.orientation.y = a.getY();
361  posemsg.orientation.z = a.getZ();
362 
363  msg.poses.push_back(posemsg);
364 
365  this->localization_visualization_pub_pose_.publish(msg);
366 }
367 
368 } // end namespace emc
369 
370 
emc::LaserData::angle_increment
double angle_increment
Definition: data.h:20
emc::Communication::~Communication
~Communication()
Definition: communication.cpp:75
emc::Communication::pub_play_
ros::Publisher pub_play_
Definition: communication.h:77
std::string
emc::Communication::bumper_f_msg_
std_msgs::BoolConstPtr bumper_f_msg_
Definition: communication.h:129
emc::Communication::laser_msg_
sensor_msgs::LaserScanConstPtr laser_msg_
Definition: communication.h:97
std::cos
T cos(T... args)
emc::Communication::pub_open_door_
ros::Publisher pub_open_door_
Definition: communication.h:73
emc::Communication::poseCallback
void poseCallback(const geometry_msgs::PoseStampedConstPtr &msg)
Definition: communication.cpp:264
std::vector< float >
emc::Communication::odom_cb_queue_
ros::CallbackQueue odom_cb_queue_
Definition: communication.h:113
emc::Communication::sendPoseEstimate
void sendPoseEstimate(const geometry_msgs::Transform &pose)
Definition: communication.cpp:238
emc::PoseData
Definition: pose.h:9
emc::Communication::sub_bumper_f_
ros::Subscriber sub_bumper_f_
Definition: communication.h:126
emc::Communication::bumper_f_cb_queue_
ros::CallbackQueue bumper_f_cb_queue_
Definition: communication.h:123
emc::LaserData::angle_min
double angle_min
Definition: data.h:18
emc::PoseData::yaw
double yaw
Definition: pose.h:16
emc::Communication::bumper_b_msg_
std_msgs::BoolConstPtr bumper_b_msg_
Definition: communication.h:130
emc::LaserData::timestamp
double timestamp
Definition: data.h:21
emc::OdometryData::x
double x
Definition: odom.h:11
emc::Communication::readPoseData
bool readPoseData(PoseData &pose)
Definition: communication.cpp:109
emc::Communication::readOdometryData
bool readOdometryData(OdometryData &odom)
Definition: communication.cpp:145
emc::OdometryData::a
double a
Definition: odom.h:13
emc::Communication::pub_speak_
ros::Publisher pub_speak_
Definition: communication.h:75
emc::Communication::odom_msg_
nav_msgs::OdometryConstPtr odom_msg_
Definition: communication.h:117
emc::Communication::init
void init()
Definition: communication.cpp:82
emc::BumperData::contact
bool contact
Definition: bumper.h:11
emc::OdometryData
Definition: odom.h:9
emc::Communication::bumper_b_cb_queue_
ros::CallbackQueue bumper_b_cb_queue_
Definition: communication.h:124
emc::Communication::localization_viz_send_laser_scan
void localization_viz_send_laser_scan(double angle_min, double angle_max, double angle_inc, int subsample, std::vector< float > prediction)
Definition: communication.cpp:293
emc::Communication::sub_odom_
ros::Subscriber sub_odom_
Definition: communication.h:115
emc::LaserData::angle_max
double angle_max
Definition: data.h:19
emc::Communication::pose_msg_
geometry_msgs::PoseStampedConstPtr pose_msg_
Definition: communication.h:107
emc::LaserData
Definition: data.h:14
emc::Communication::localization_viz_send_particles
void localization_viz_send_particles(int N, std::vector< std::vector< double >> particle_poses, double mapOrientation)
Definition: communication.cpp:313
emc::Communication::pub_tf2
std::unique_ptr< tf2_ros::TransformBroadcaster > pub_tf2
Definition: communication.h:88
emc::Communication::pub_base_ref_
ros::Publisher pub_base_ref_
Definition: communication.h:71
emc::Communication::laser_cb_queue_
ros::CallbackQueue laser_cb_queue_
Definition: communication.h:93
emc::Communication::localization_visualization_pub_particle_
ros::Publisher localization_visualization_pub_particle_
Definition: communication.h:83
emc::PoseData::x
double x
Definition: pose.h:11
emc::Communication::sub_bumper_b_
ros::Subscriber sub_bumper_b_
Definition: communication.h:127
emc::Communication::odomCallback
void odomCallback(const nav_msgs::OdometryConstPtr &msg)
Definition: communication.cpp:271
emc::LaserData::range_max
double range_max
Definition: data.h:17
emc::PoseData::z
double z
Definition: pose.h:13
emc::LaserData::range_min
double range_min
Definition: data.h:16
emc::PoseData::y
double y
Definition: pose.h:12
emc::Communication::sendBaseVelocity
void sendBaseVelocity(double vx, double vy, double va)
Definition: communication.cpp:197
std::sin
T sin(T... args)
emc::Communication::sub_pose_
ros::Subscriber sub_pose_
Definition: communication.h:105
emc::PoseData::roll
double roll
Definition: pose.h:14
emc::Communication::speak
void speak(const std::string &text)
Definition: communication.cpp:224
communication.h
emc::Communication::pub_marker_
ros::Publisher pub_marker_
Definition: communication.h:79
emc::Communication::localization_viz_send_pose
void localization_viz_send_pose(std::vector< double > pose, double mapOrientation)
Definition: communication.cpp:342
emc::Communication::sendMarker
void sendMarker(visualization_msgs::Marker marker)
Definition: communication.cpp:217
emc::Communication::sendOpendoorRequest
void sendOpendoorRequest()
Definition: communication.cpp:209
emc::PoseData::pitch
double pitch
Definition: pose.h:15
emc::Communication::bumperbCallback
void bumperbCallback(const std_msgs::BoolConstPtr &msg)
Definition: communication.cpp:285
emc::Communication::localization_visualization_pub_laser_msg_
ros::Publisher localization_visualization_pub_laser_msg_
Definition: communication.h:82
emc
Definition: bumper.h:4
emc::OdometryData::y
double y
Definition: odom.h:12
emc::Communication::readFrontBumperData
bool readFrontBumperData(BumperData &bumper)
Definition: communication.cpp:167
emc::Communication::pose_cb_queue_
ros::CallbackQueue pose_cb_queue_
Definition: communication.h:103
emc::Communication::sub_laser_
ros::Subscriber sub_laser_
Definition: communication.h:95
emc::Communication::localization_visualization_pub_pose_
ros::Publisher localization_visualization_pub_pose_
Definition: communication.h:84
emc::Communication::laserCallback
void laserCallback(const sensor_msgs::LaserScanConstPtr &msg)
Definition: communication.cpp:257
emc::Communication::play
void play(const std::string &file)
Definition: communication.cpp:231
std::unique_ptr< tf2_ros::TransformBroadcaster >
emc::Communication::readBackBumperData
bool readBackBumperData(BumperData &bumper)
Definition: communication.cpp:182
emc::Communication::Communication
Communication(std::string robot_name="pyro")
Definition: communication.cpp:20
emc::Communication::readLaserData
bool readLaserData(LaserData &scan)
Definition: communication.cpp:88
emc::LaserData::ranges
std::vector< float > ranges
Definition: data.h:22
emc::Communication::robot_frame_name
std::string robot_frame_name
Definition: communication.h:136
emc::OdometryData::timestamp
double timestamp
Definition: odom.h:14
emc::BumperData
Definition: bumper.h:9
emc::Communication::bumperfCallback
void bumperfCallback(const std_msgs::BoolConstPtr &msg)
Definition: communication.cpp:278
string