servers.cpp
Go to the documentation of this file.
2 #include <boost/foreach.hpp>
3 #include <cv_bridge/cv_bridge.h>
4 #include <fstream>
5 #include <opencv-3.3.1-dev/opencv2/opencv.hpp>
6 #include <opencv-3.3.1-dev/opencv2/videoio.hpp>
7 #include <ros/ros.h>
8 #include <rosbag/bag.h>
9 #include <rosbag/view.h>
10 #include <rqt_bag_exporter/CloseBag.h>
11 #include <rqt_bag_exporter/EstimateVideoFps.h>
12 #include <rqt_bag_exporter/ExportToCSVAction.h>
13 #include <rqt_bag_exporter/ExportToVideoAction.h>
14 #include <rqt_bag_exporter/GetDuration.h>
15 #include <rqt_bag_exporter/ListTopics.h>
16 #include <rqt_bag_exporter/OpenBag.h>
17 #include <sensor_msgs/CompressedImage.h>
18 #include <std_msgs/Bool.h>
19 #include <std_msgs/Duration.h>
20 #include <std_msgs/Float32.h>
21 #include <std_msgs/Float64.h>
22 #include <std_msgs/Int16.h>
23 #include <std_msgs/Int32.h>
24 #include <std_msgs/Int64.h>
25 #include <std_msgs/Int8.h>
26 #include <std_msgs/String.h>
27 #include <std_msgs/Time.h>
28 #include <std_msgs/UInt16.h>
29 #include <std_msgs/UInt32.h>
30 #include <std_msgs/UInt64.h>
31 #include <std_msgs/UInt8.h>
32 #include <string>
33 
34 std::shared_ptr<rosbag::Bag> bag;
35 std::string bag_file_name("");
36 
38 {
39  gh.setAccepted();
40  rqt_bag_exporter::ExportToVideoGoal goal(*gh.getGoal());
41  rqt_bag_exporter::ExportToVideoResult result;
42  rqt_bag_exporter::ExportToVideoFeedback feedback;
43 
44  if (!bag || bag->getSize() <= 0)
45  {
46  result.error = "No valid bag file is opened, call open_bag service to open one.";
47  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
48  gh.setAborted(result);
49  return;
50  }
51 
52  std::string file_name(bag_file_name);
53  int pos(file_name.find_last_of("."));
54  file_name.erase(pos, std::string::npos);
55  pos = file_name.find_last_of("/");
56  file_name.erase(0, pos + 1);
57  std::string topic_name(goal.topic_name);
58  pos = topic_name.find_first_of("/");
59  topic_name.erase(0, pos + 1);
60  std::replace(topic_name.begin(), topic_name.end(), '/', '_');
61 
62  std::vector<std::string> topics;
63  topics.push_back(goal.topic_name);
64  rosbag::View view(*bag, rosbag::TopicQuery(topics));
65  if (view.size() == 0)
66  {
67  result.error = "Topic '" + goal.topic_name + "' doesn't exist in this bag file";
68  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
69  gh.setAborted(result);
70  return;
71  }
72 
73  feedback.progress_msg = "Starting...";
74  feedback.progress_value = 0;
75  gh.publishFeedback(feedback);
76 
77  cv::VideoWriter video;
78 
79  // Retrieve first image to get image info
80  // Open video file
81  const std::string video_name(goal.directory + "/" + file_name + "_" + topic_name + ".mkv");
82  BOOST_FOREACH(rosbag::MessageInstance const first, view)
83  {
84  sensor_msgs::CompressedImage::ConstPtr s = first.instantiate<sensor_msgs::CompressedImage>();
85  if (s == NULL)
86  continue;
87  try
88  {
89  cv::Mat image = cv::imdecode(s->data, 1); // Convert compressed image data to cv::Mat
90  if (!video.open(video_name, cv::VideoWriter::fourcc('X', '2', '6', '4'), goal.fps, image.size()))
91  {
92  result.error = "Cannot open video file for writing";
93  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
94  gh.setAborted(result);
95  return;
96  }
97  }
98  catch (cv_bridge::Exception& e)
99  {
100  result.error = "Could not convert image";
101  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
102  gh.setAborted(result);
103  return;
104  }
105  break;
106  }
107 
108  ros::Time rosbag_begin(view.getBeginTime());
109  BOOST_FOREACH(rosbag::MessageInstance const m, view)
110  {
111  if (gh.getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE)
112  return;
113 
114  if ((rosbag_begin.toSec() + goal.start_time) > m.getTime().toSec())
115  continue;
116 
117  if ((rosbag_begin.toSec() + goal.end_time) < m.getTime().toSec())
118  break;
119 
120  long unsigned real_time(m.getTime().sec - (rosbag_begin.sec + goal.start_time));
121  long unsigned coeficient(100 / (goal.end_time - goal.start_time));
122  long unsigned transmit_value(real_time * coeficient);
123  feedback.progress_msg = "Exporting video topic " + goal.topic_name;
124  feedback.progress_value = transmit_value;
125  gh.publishFeedback(feedback);
126  sensor_msgs::CompressedImage::ConstPtr s = m.instantiate<sensor_msgs::CompressedImage>();
127  if (s == NULL)
128  continue;
129  try
130  {
131  cv::Mat image = cv::imdecode(s->data, 1); // Convert compressed image data to cv::Mat
132  video << image;
133  }
134  catch (cv_bridge::Exception& e)
135  {
136  result.error = "Could not convert image";
137  gh.setAborted(result);
138  return;
139  }
140  }
141 
142  feedback.progress_msg = "Writing video file";
143  feedback.progress_value = 100;
144  gh.publishFeedback(feedback);
145  video.release();
146 
147  feedback.progress_msg = "Success";
148  feedback.progress_value = 100;
149  gh.publishFeedback(feedback);
150  ros::Duration(0.5).sleep();
151  gh.setSucceeded(result);
152 }
153 
155 {
156  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE
157  || gh.getGoalStatus().status == actionlib_msgs::GoalStatus::PREEMPTING)
158  gh.setCanceled();
159 }
160 
162 {
163  gh.setAccepted();
164  rqt_bag_exporter::ExportToCSVGoal goal;
165  rqt_bag_exporter::ExportToCSVResult result;
166  rqt_bag_exporter::ExportToCSVFeedback feedback;
167  goal = *gh.getGoal();
168 
169  if (!bag || bag->getSize() <= 0)
170  {
171  result.error = "No valid bag file is opened, call open_bag service to open one.";
172  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
173  gh.setAborted(result);
174  return;
175  }
176 
177  std::vector<std::string> topics;
178  topics.push_back(goal.topic_name);
179  rosbag::View view(*bag, rosbag::TopicQuery(topics));
180  if (view.size() == 0)
181  {
182  result.error = "Topic '" + goal.topic_name + "' doesn't exist in this bag file";
183  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
184  gh.setAborted(result);
185  return;
186  }
187 
188  feedback.progress_msg = "Starting CSV export";
189  feedback.progress_value = 0;
190  gh.publishFeedback(feedback);
191 
192  std::ofstream csv_file;
193  std::string file_name(bag_file_name);
194  int pos = file_name.find_last_of(".");
195  file_name.erase(pos, std::string::npos);
196  pos = file_name.find_last_of("/");
197  file_name.erase(0, pos + 1);
198  std::string topic_name(goal.topic_name);
199  pos = topic_name.find_first_of("/");
200  topic_name.erase(0, pos + 1);
201  std::replace(topic_name.begin(), topic_name.end(), '/', '_');
202  std::string path_file(goal.directory + "/" + file_name + "_" + topic_name + ".csv");
203  csv_file.open(path_file);
204  if (!csv_file.is_open())
205  {
206  result.error = "Failed to open CSV file " + path_file;
207  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE)
208  gh.setAborted(result);
209  return;
210  }
211  csv_file << "Time, " << goal.topic_name << std::endl;
212  ros::Time rosbag_begin(view.getBeginTime());
213  BOOST_FOREACH(rosbag::MessageInstance const m, view)
214  {
215  if (gh.getGoalStatus().status != actionlib_msgs::GoalStatus::ACTIVE)
216  return;
217  if ((rosbag_begin.toSec() + goal.start_time) > m.getTime().toSec())
218  {
219  continue;
220  }
221  if ((rosbag_begin.toSec() + goal.end_time) < m.getTime().toSec())
222  {
223  break;
224  }
225  std::uint64_t real_time(m.getTime().sec - (rosbag_begin.sec + goal.start_time));
226  std::uint64_t coeficient(100 / (goal.end_time - goal.start_time));
227  std::uint64_t transmit_value(real_time * coeficient);
228  std::string transmit_msg("Exporting topic " + goal.topic_name);
229  feedback.progress_msg = transmit_msg;
230  feedback.progress_value = transmit_value;
231  gh.publishFeedback(feedback);
232  double time(m.getTime().toSec() - (rosbag_begin.toSec() + goal.start_time));
233 
234  std_msgs::Float32::ConstPtr ft_32 = m.instantiate<std_msgs::Float32>();
235  if (ft_32 != NULL)
236  csv_file << time << ", " << ft_32->data << std::endl;
237 
238  std_msgs::Float64::ConstPtr ft_64 = m.instantiate<std_msgs::Float64>();
239  if (ft_64 != NULL)
240  csv_file << time << ", " << ft_64->data << std::endl;
241 
242  std_msgs::Int8::ConstPtr int_8 = m.instantiate<std_msgs::Int8>();
243  if (int_8 != NULL)
244  csv_file << time << ", " << int_8->data << std::endl;
245 
246  std_msgs::Int16::ConstPtr int_16 = m.instantiate<std_msgs::Int16>();
247  if (int_16 != NULL)
248  csv_file << time << ", " << int_16->data << std::endl;
249 
250  std_msgs::Int32::ConstPtr int_32 = m.instantiate<std_msgs::Int32>();
251  if (int_32 != NULL)
252  csv_file << time << ", " << int_32->data << std::endl;
253 
254  std_msgs::Int64::ConstPtr int_64 = m.instantiate<std_msgs::Int64>();
255  if (int_64 != NULL)
256  csv_file << time << ", " << int_64->data << std::endl;
257 
258  std_msgs::UInt8::ConstPtr uint_8 = m.instantiate<std_msgs::UInt8>();
259  if (uint_8 != NULL)
260  csv_file << time << ", " << uint_8->data << std::endl;
261 
262  std_msgs::UInt16::ConstPtr uint_16 = m.instantiate<std_msgs::UInt16>();
263  if (uint_16 != NULL)
264  csv_file << time << ", " << uint_16->data << std::endl;
265 
266  std_msgs::UInt32::ConstPtr uint_32 = m.instantiate<std_msgs::UInt32>();
267  if (uint_32 != NULL)
268  csv_file << time << ", " << uint_32->data << std::endl;
269 
270  std_msgs::UInt64::ConstPtr uint_64 = m.instantiate<std_msgs::UInt64>();
271  if (uint_64 != NULL)
272  csv_file << time << ", " << uint_64->data << std::endl;
273 
274  std_msgs::Bool::ConstPtr Bool_ = m.instantiate<std_msgs::Bool>();
275  if (Bool_ != NULL)
276  csv_file << time << ", " << (Bool_->data ? "True" : "False") << std::endl;
277 
278  std_msgs::Duration::ConstPtr dur = m.instantiate<std_msgs::Duration>();
279  if (dur != NULL)
280  csv_file << time << ", " << dur->data << std::endl;
281 
282  std_msgs::String::ConstPtr str = m.instantiate<std_msgs::String>();
283  if (str != NULL)
284  csv_file << time << ", " << str->data << std::endl;
285 
286  std_msgs::Time::ConstPtr time_ = m.instantiate<std_msgs::Time>();
287  if (time_ != NULL)
288  csv_file << time << ", " << time_->data.toSec() << std::endl;
289  }
290 
291  feedback.progress_msg = "Writing CSV file";
292  feedback.progress_value = 100;
293  gh.publishFeedback(feedback);
294 
295  csv_file.close();
296  feedback.progress_msg = "Sucess";
297  feedback.progress_value = 100;
298  gh.publishFeedback(feedback);
299  ros::Duration(0.25).sleep();
300 
301  gh.setSucceeded(result);
302  return;
303 }
304 
306 {
307  if (gh.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE
308  || gh.getGoalStatus().status == actionlib_msgs::GoalStatus::PREEMPTING)
309  gh.setCanceled();
310 }
311 
312 bool openBag(rqt_bag_exporter::OpenBag::Request &req,
313  rqt_bag_exporter::OpenBag::Response &res)
314 {
315  bag_file_name.clear();
316  if (req.bag_file.find(".bag") == std::string::npos)
317  {
318  res.error = "Not a bag file";
319  return true;
320  }
321 
322  if (bag)
323  bag->close();
324 
325  bag.reset(new rosbag::Bag);
326  try
327  {
328  bag->open(req.bag_file, rosbag::bagmode::Read);
329  }
330  catch (rosbag::BagException &e)
331  {
332  res.error = e.what();
333  return true;
334  }
335 
336  bag_file_name = req.bag_file;
337  return true;
338 }
339 
340 bool closeBag(rqt_bag_exporter::CloseBag::Request &,
341  rqt_bag_exporter::CloseBag::Response &)
342 {
343  if (!bag || bag->getSize() != 0)
344  return true;
345 
346  bag->close();
347  return true;
348 }
349 
350 bool listTopics(rqt_bag_exporter::ListTopics::Request &,
351  rqt_bag_exporter::ListTopics::Response &res)
352 {
353  if (!bag || bag->getSize() <= 0)
354  {
355  res.error = "No valid bag file is opened, call open_bag service to open one.";
356  return true;
357  }
358 
359  rosbag::View view(*bag);
360  std::vector<const rosbag::ConnectionInfo *> connection_infos = view.getConnections();
361  BOOST_FOREACH(const rosbag::ConnectionInfo *info, connection_infos)
362  {
363  res.topics_name.push_back(info->topic);
364  res.topics_type.push_back(info->datatype);
365  }
366  return true;
367 }
368 
369 bool estimateVideoFps(rqt_bag_exporter::EstimateVideoFps::Request &req,
370  rqt_bag_exporter::EstimateVideoFps::Response &res)
371 {
372  if (!bag || bag->getSize() <= 0)
373  {
374  res.error = "No valid bag file is opened, call open_bag service to open one.";
375  return true;
376  }
377 
378  rosbag::View view(*bag, rosbag::TopicQuery(req.topic_name));
379  res.fps = view.size() / (view.getEndTime().sec - view.getBeginTime().sec);
380  return true;
381 }
382 
383 bool getDuration(rqt_bag_exporter::GetDuration::Request &,
384  rqt_bag_exporter::GetDuration::Response &res)
385 {
386  if (!bag || bag->getSize() <= 0)
387  {
388  res.error = "No valid bag file is opened, call open_bag service to open one.";
389  return true;
390  }
391 
392  rosbag::View view(*bag);
393  res.duration = view.getEndTime().toSec() - view.getBeginTime().toSec();
394  return true;
395 }
396 
397 int main(int argc,
398  char** argv)
399 {
400  ros::init(argc, argv, "rqt_bag_exporter_servers");
401  ros::NodeHandle nh;
403  spinner.start();
404 
406  "export_csv",
407  &exportCsv,
409  false);
410  action_server_1.start();
411 
413  "export_video",
414  &exportVideo,
416  false);
417  action_server_2.start();
418 
419  ros::ServiceServer service_1 = nh.advertiseService("open_bag", openBag);
420  ros::ServiceServer service_2 = nh.advertiseService("close_bag", closeBag);
421  ros::ServiceServer service_3 = nh.advertiseService("list_topics", listTopics);
422  ros::ServiceServer service_4 = nh.advertiseService("estimate_video_fps", estimateVideoFps);
423  ros::ServiceServer service_5 = nh.advertiseService("get_duration", getDuration);
424 
426  spinner.stop();
427  return 0;
428 }
void exportVideoCancelCb(actionlib::ServerGoalHandle< rqt_bag_exporter::ExportToVideoAction > gh)
Definition: servers.cpp:154
void exportVideo(actionlib::ServerGoalHandle< rqt_bag_exporter::ExportToVideoAction > gh)
Definition: servers.cpp:37
void publishFeedback(const Feedback &feedback)
std::vector< const ConnectionInfo * > getConnections()
std::string bag_file_name("")
std::shared_ptr< rosbag::Bag > bag
Definition: servers.cpp:34
XmlRpcServer s
bool sleep() const
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
boost::shared_ptr< const Goal > getGoal() const
void exportCsvCancelCb(actionlib::ServerGoalHandle< rqt_bag_exporter::ExportToCSVAction > gh)
Definition: servers.cpp:305
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
void setCanceled(const Result &result=Result(), const std::string &text=std::string(""))
void spinner()
ros::Time const & getTime() const
uint32_t size()
void exportCsv(actionlib::ServerGoalHandle< rqt_bag_exporter::ExportToCSVAction > gh)
Definition: servers.cpp:161
void setAccepted(const std::string &text=std::string(""))
bool closeBag(rqt_bag_exporter::CloseBag::Request &, rqt_bag_exporter::CloseBag::Response &)
Definition: servers.cpp:340
void setSucceeded(const Result &result=Result(), const std::string &text=std::string(""))
int main(int argc, char **argv)
Definition: servers.cpp:397
ros::Time getBeginTime()
boost::shared_ptr< T > instantiate() const
bool getDuration(rqt_bag_exporter::GetDuration::Request &, rqt_bag_exporter::GetDuration::Response &res)
Definition: servers.cpp:383
void setAborted(const Result &result=Result(), const std::string &text=std::string(""))
ros::Time getEndTime()
bool estimateVideoFps(rqt_bag_exporter::EstimateVideoFps::Request &req, rqt_bag_exporter::EstimateVideoFps::Response &res)
Definition: servers.cpp:369
bool openBag(rqt_bag_exporter::OpenBag::Request &req, rqt_bag_exporter::OpenBag::Response &res)
Definition: servers.cpp:312
bool listTopics(rqt_bag_exporter::ListTopics::Request &, rqt_bag_exporter::ListTopics::Response &res)
Definition: servers.cpp:350
actionlib_msgs::GoalStatus getGoalStatus() const
ROSCPP_DECL void waitForShutdown()


rqt_bag_exporter
Author(s): Romain Hernandez, Victor Lamoine - Institut Maupertuis
autogenerated on Mon Jun 10 2019 14:57:01