trajectory_utils.cpp
Go to the documentation of this file.
1 #include <mutex>
2 #include <string>
3 #include <strings.h>
4 
5 #include <ram_msgs/AdditiveManufacturingTrajectory.h>
6 #include <ram_trajectory_utils/BufferParams.h>
7 #include <ram_trajectory_utils/ExportTrajectory.h>
8 #include <ram_trajectory_utils/ImportTrajectory.h>
9 #include <ram_trajectory_utils/UnmodifiedTrajectory.h>
10 #include <ros/ros.h>
11 #include <rosbag/bag.h>
12 #include <rosbag/buffer.h>
13 #include <rosbag/exceptions.h>
14 #include <rosbag/structures.h>
15 #include <rosbag/view.h>
16 #include <signal.h>
17 
19 
20 const unsigned msg_to_keep(10);
21 unsigned last_msg_published = 0;
23 
24 std::mutex msgs_mutex;
25 std::vector<ram_msgs::AdditiveManufacturingTrajectory> traj_msgs; // Buffer 1. Contain all msgs
26 
28 std::vector<ram_msgs::AdditiveManufacturingTrajectory> unmodified_traj_msgs; // Buffer 2. Contain just the unmodified msgs
29 
30 // On shutdown, write bag file containing last trajectories
31 void mySigintHandler(int)
32 {
33  std::lock_guard<std::mutex> lock(msgs_mutex);
34  std::lock_guard<std::mutex> lock_1(unmodified_msgs_mutex);
35 
36  if ((last_msg_published + 1) < traj_msgs.size()) // erase msgs
37  {
38  traj_msgs.erase((traj_msgs.begin() + last_msg_published + 1), traj_msgs.end());
39  // Erase msgs in the second buffer
40  while (unmodified_traj_msgs.back().generated != traj_msgs.back().generated && !unmodified_traj_msgs.empty())
41  unmodified_traj_msgs.pop_back();
42  }
43 
44  buffer_bag.open("ram_buffer_trajectory.bag", rosbag::bagmode::Write);
45  for (auto msg : traj_msgs)
46  buffer_bag.write("ram/trajectory", ros::Time::now(), msg);
47  buffer_bag.close();
48 
49  buffer_bag.open("ram_buffer_unmodified_trajectory.bag", rosbag::bagmode::Write);
50  for (auto msg : unmodified_traj_msgs)
51  buffer_bag.write("ram/trajectory", ros::Time::now(), msg);
52  buffer_bag.close();
53 
54  ros::shutdown();
55 }
56 
58 {
59  if (ros::this_node::getName().compare(msg_event.getPublisherName()) == 0) // The publisher is himself
60  return;
61 
62  std::lock_guard<std::mutex> lock(msgs_mutex);
63  std::lock_guard<std::mutex> lock_1(unmodified_msgs_mutex);
64 
65  if ((last_msg_published + 1) < traj_msgs.size()) // erase msgs
66  {
67  traj_msgs.erase((traj_msgs.begin() + last_msg_published + 1), traj_msgs.end());
68  // Erase msgs in the second buffer
69  while (unmodified_traj_msgs.back().generated != traj_msgs.back().generated && !unmodified_traj_msgs.empty())
70  unmodified_traj_msgs.pop_back();
71  }
72 
74  traj_msgs.push_back(*msg_event.getMessage());
75 
76  if (msg_event.getMessage()->generated == msg_event.getMessage()->modified) // the trajectory is not modified
77  unmodified_traj_msgs.push_back(*msg_event.getMessage());
78  // Always save the same numbers of elements
79  if (traj_msgs.size() > msg_to_keep)
80  {
81  traj_msgs.erase(traj_msgs.begin(), traj_msgs.end() - msg_to_keep);
82  last_msg_published = traj_msgs.size() - 1;
83  }
84  if (unmodified_traj_msgs.size() > msg_to_keep)
86 }
87 
88 bool trajectoryBufferCallback(ram_trajectory_utils::BufferParams::Request &req,
89  ram_trajectory_utils::BufferParams::Response &res)
90 {
91  std::lock_guard<std::mutex> lock(msgs_mutex);
92 
93  ram_msgs::AdditiveManufacturingTrajectory trajectory;
94  switch (req.button_id)
95  {
96  case 1:
97  // Back button
98  if (last_msg_published > 0)
100  else
101  {
102  res.error = "Start of the buffer";
103  return true;
104  }
105  break;
106  case 2:
107  // Forward button
108  if ((last_msg_published + 1) < traj_msgs.size())
110  else
111  {
112  res.error = "End of the buffer";
113  return true;
114  }
115  break;
116  }
117 
118  if (last_msg_published < traj_msgs.size())
119  {
120  // Trajectory is published
121  trajectory = traj_msgs[last_msg_published];
122  pub.publish(trajectory);
123  }
124 
125  res.error.clear();
126  return true;
127 }
128 
129 bool getUnmodifiedTrajectoryCallback(ram_trajectory_utils::UnmodifiedTrajectory::Request &req,
130  ram_trajectory_utils::UnmodifiedTrajectory::Response &res)
131 {
132  std::lock_guard<std::mutex> lock_1(unmodified_msgs_mutex);
133  for (auto msg : unmodified_traj_msgs)
134  {
135  if (msg.generated == req.generated)
136  {
137  res.trajectory = msg;
138  return true;
139  }
140  }
141 
142  return false;
143 }
144 
145 std::string fileExtension(const std::string full_path)
146 {
147  size_t last_index = full_path.find_last_of("/");
148  std::string file_name = full_path.substr(last_index + 1, full_path.size());
149 
150  last_index = file_name.find_last_of("\\");
151  file_name = file_name.substr(last_index + 1, file_name.size());
152 
153  last_index = file_name.find_last_of(".");
154  if (last_index == std::string::npos)
155  return "";
156 
157  return file_name.substr(last_index + 1, file_name.size());
158 }
159 
160 bool exportTrajectoryCallback(ram_trajectory_utils::ExportTrajectory::Request &req,
161  ram_trajectory_utils::ExportTrajectory::Response &res)
162 {
163  std::lock_guard<std::mutex> lock(msgs_mutex);
164  std::lock_guard<std::mutex> lock_1(unmodified_msgs_mutex);
165 
166  std::string file_extension(fileExtension(req.file_name));
167  if (file_extension.compare("bag") != 0)
168  {
169  res.error = req.file_name + " is not a bag file";
170  return true;
171  }
172 
173  // Find current trajectory
174  if (last_msg_published >= traj_msgs.size())
175  {
176  res.error = "Current trajectory is empty";
177  return true;
178  }
179 
180  ram_msgs::AdditiveManufacturingTrajectory current_traj = traj_msgs[last_msg_published];
181  ram_msgs::AdditiveManufacturingTrajectory unmodified_current_traj = current_traj;
182 
183  if (current_traj.poses.size() == 0)
184  {
185  res.error = "Current trajectory is empty";
186  return true;
187  }
188 
189  // Find unmodified trajectory
190  bool trajectory_in_buffer = false;
191  for (auto msg : unmodified_traj_msgs)
192  {
193  if (current_traj.generated != msg.generated)
194  continue;
195  // Trajectories are equals
196  trajectory_in_buffer = true;
197  if (current_traj.modified != msg.modified)
198  {
199  unmodified_current_traj = msg;
200  break;
201  }
202  }
203 
204  if (!trajectory_in_buffer)
205  {
206  res.error = "Corresponding unmodified trajectory does not exist in the buffer";
207  return true;
208  }
209 
210  // Save trajectory
211  rosbag::Bag export_trajectoy_bag;
212  try
213  {
214  export_trajectoy_bag.open(req.file_name, rosbag::bagmode::Write);
215  export_trajectoy_bag.write("ram/trajectory", ros::Time::now(), current_traj);
216  export_trajectoy_bag.write("ram/trajectory", ros::Time::now(), unmodified_current_traj);
217  export_trajectoy_bag.close();
218  }
219  catch (rosbag::BagException &e)
220  {
221  export_trajectoy_bag.close();
222  ROS_ERROR_STREAM(e.what());
223  res.error = e.what();
224  return true;
225  }
226 
227  return true;
228 }
229 
230 bool importTrajectoryCallback(ram_trajectory_utils::ImportTrajectory::Request &req,
231  ram_trajectory_utils::ImportTrajectory::Response &res)
232 {
233  std::lock_guard<std::mutex> lock(msgs_mutex);
234  std::lock_guard<std::mutex> lock_1(unmodified_msgs_mutex);
235 
236  std::string file_extension(fileExtension(req.file_name));
237  if (file_extension.compare("bag") != 0)
238  {
239  res.error = req.file_name + " is not a bag file";
240  return true;
241  }
242 
243  rosbag::Bag import_trajectoy_bag;
244 
245  std::vector<ram_msgs::AdditiveManufacturingTrajectory> msgs_from_file;
246  try
247  {
248  import_trajectoy_bag.open(req.file_name, rosbag::bagmode::Read);
249  std::vector<std::string> topics;
250  topics.push_back(std::string("ram/trajectory"));
251  rosbag::View view(import_trajectoy_bag, rosbag::TopicQuery(topics));
252 
253  for (auto m : view)
254  {
255  ram_msgs::AdditiveManufacturingTrajectory::ConstPtr s =
256  m.instantiate<ram_msgs::AdditiveManufacturingTrajectory>();
257  if (s != NULL)
258  msgs_from_file.push_back(*s);
259  }
260 
261  import_trajectoy_bag.close();
262  }
263  catch (rosbag::BagException &e)
264  {
265  import_trajectoy_bag.close();
266  ROS_ERROR_STREAM(e.what());
267  res.error = e.what();
268  return true;
269  }
270 
271  if (msgs_from_file.size() != 2)
272  {
273  res.error = "Unable to import trajectory";
274  return true;
275  }
276 
277  // Save trajectories
278  ram_msgs::AdditiveManufacturingTrajectory trajectory = msgs_from_file[0];
279  ram_msgs::AdditiveManufacturingTrajectory unmodified_trajectory = msgs_from_file[1];
280 
281  if (trajectory.poses.size() == 0)
282  {
283  res.error = "Trajectory is empty";
284  return true;
285  }
286 
287  // Save unmodified_trajectory
288  for (unsigned i(0); i < unmodified_traj_msgs.size(); ++i)
289  {
290  if (unmodified_trajectory.generated == unmodified_traj_msgs[i].generated)
291  {
292  unmodified_traj_msgs.erase(unmodified_traj_msgs.begin() + i); // avoid duplicate duplicate in unmodified buffer
293  break;
294  }
295  }
296  // Save trajectories
297  unmodified_traj_msgs.push_back(unmodified_trajectory);
298  traj_msgs.push_back(trajectory);
299  last_msg_published = traj_msgs.size() - 1;
300 
301  // Publish trajectory
302  pub.publish(trajectory);
303  return true;
304 }
305 
306 int main(int argc,
307  char **argv)
308 {
309  ros::init(argc, argv, "ram_trajectory_utils", ros::init_options::NoSigintHandler);
310  signal(SIGINT, mySigintHandler);
312 
313  bool error_in_first_bag = false;
314  bool error_in_second_bag = false;
315 
316  // Read the bag file (first buffer)
317  try
318  {
319  buffer_bag.open("ram_buffer_trajectory.bag", rosbag::bagmode::Read);
320  std::vector<std::string> topics;
321  topics.push_back(std::string("ram/trajectory"));
322  rosbag::View view(buffer_bag, rosbag::TopicQuery(topics));
323  std::lock_guard<std::mutex> lock(msgs_mutex);
324 
325  for (auto m : view)
326  {
327  ram_msgs::AdditiveManufacturingTrajectory::ConstPtr s =
328  m.instantiate<ram_msgs::AdditiveManufacturingTrajectory>();
329  if (s != NULL)
330  traj_msgs.push_back(*s);
331  }
332 
333  last_msg_published = traj_msgs.size(); // There are not published trajectories
334  buffer_bag.close();
335  }
336  catch (rosbag::BagException &e)
337  {
338  buffer_bag.close();
339  ROS_WARN_STREAM(e.what());
340 
341  std::string file(getenv("HOME"));
342  file += "/.ros/ram_buffer_trajectory.bag";
343 
344  if (std::remove(file.c_str()) == 0)
345  ROS_WARN_STREAM(file << " was removed because corrupted");
346 
347  error_in_first_bag = true;
348  }
349 
350  // Read the bag file (second buffer)
351  try
352  {
353  buffer_bag.open("ram_buffer_unmodified_trajectory.bag", rosbag::bagmode::Read);
354  std::vector<std::string> topics;
355  topics.push_back(std::string("ram/trajectory"));
356  rosbag::View view(buffer_bag, rosbag::TopicQuery(topics));
357  std::lock_guard<std::mutex> lock_1(unmodified_msgs_mutex);
358 
359  for (auto m : view)
360  {
361  ram_msgs::AdditiveManufacturingTrajectory::ConstPtr s =
362  m.instantiate<ram_msgs::AdditiveManufacturingTrajectory>();
363  if (s != NULL)
364  unmodified_traj_msgs.push_back(*s);
365  }
366  buffer_bag.close();
367  }
368  catch (rosbag::BagException &e)
369  {
370  buffer_bag.close();
371  ROS_WARN_STREAM(e.what());
372 
373  std::string file(getenv("HOME"));
374  file += "/.ros/ram_buffer_unmodified_trajectory.bag";
375 
376  if (std::remove(file.c_str()) == 0)
377  ROS_WARN_STREAM(file << " was removed because corrupted");
378 
379  error_in_second_bag = true;
380  }
381 
382  if (error_in_first_bag || error_in_second_bag)
383  {
384  traj_msgs.clear();
385  unmodified_traj_msgs.clear();
386  last_msg_published = 0;
387  }
388  // Publish on "ram/trajectory"
389  pub = nh.advertise<ram_msgs::AdditiveManufacturingTrajectory>("ram/trajectory", msg_to_keep, true);
390 
391  // Subscribe on "ram/trajectory"
392  ros::Subscriber sub = nh.subscribe("ram/trajectory", msg_to_keep, saveTrajectoryCallback);
393  ros::ServiceServer service_1 = nh.advertiseService("ram/buffer/get_trajectory", trajectoryBufferCallback);
394  ros::ServiceServer service_2 = nh.advertiseService("ram/buffer/get_unmodified_trajectory",
396  ros::ServiceServer service_3 = nh.advertiseService("ram/buffer/export_trajectory", exportTrajectoryCallback);
397  ros::ServiceServer service_4 = nh.advertiseService("ram/buffer/import_trajectory", importTrajectoryCallback);
398 
399  ros::AsyncSpinner spinner(1);
400  spinner.start();
402 
403  return 0;
404 }
const unsigned msg_to_keep(10)
std::mutex msgs_mutex
bool exportTrajectoryCallback(ram_trajectory_utils::ExportTrajectory::Request &req, ram_trajectory_utils::ExportTrajectory::Response &res)
void publish(const boost::shared_ptr< M > &message) const
void open(std::string const &filename, uint32_t mode=bagmode::Read)
bool importTrajectoryCallback(ram_trajectory_utils::ImportTrajectory::Request &req, ram_trajectory_utils::ImportTrajectory::Response &res)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
unsigned last_msg_published
XmlRpcServer s
std::mutex unmodified_msgs_mutex
std::unique_ptr< ros::NodeHandle > nh
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
ROSCPP_DECL const std::string & getName()
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
void close()
std::vector< ram_msgs::AdditiveManufacturingTrajectory > traj_msgs
const std::string & getPublisherName() const
std::vector< ram_msgs::AdditiveManufacturingTrajectory > unmodified_traj_msgs
ros::Publisher pub
rosbag::Bag buffer_bag
bool getUnmodifiedTrajectoryCallback(ram_trajectory_utils::UnmodifiedTrajectory::Request &req, ram_trajectory_utils::UnmodifiedTrajectory::Response &res)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
#define ROS_WARN_STREAM(args)
int main(int argc, char **argv)
bool trajectoryBufferCallback(ram_trajectory_utils::BufferParams::Request &req, ram_trajectory_utils::BufferParams::Response &res)
void saveTrajectoryCallback(const ros::MessageEvent< ram_msgs::AdditiveManufacturingTrajectory > &msg_event)
static Time now()
ROSCPP_DECL void shutdown()
#define ROS_ERROR_STREAM(args)
void mySigintHandler(int)
std::string fileExtension(const std::string full_path)
void write(std::string const &topic, ros::MessageEvent< T > const &event)
boost::shared_ptr< M > getMessage() const
ROSCPP_DECL void waitForShutdown()


ram_trajectory_utils
Author(s): Andres Campos - Institut Maupertuis
autogenerated on Fri Oct 27 2017 02:49:34