rcdynamics_stream.cc
Go to the documentation of this file.
1 /*
2  * This file is part of the rc_dynamics_api package.
3  *
4  * Copyright (c) 2017 Roboception GmbH
5  * All rights reserved
6  *
7  * Author: Christian Emmerich
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the copyright holder nor the names of its contributors
20  * may be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include <fstream>
37 #include <signal.h>
38 #include <chrono>
39 #include <iomanip>
40 
42 #include "csv_printing.h"
43 
44 #ifdef WIN32
45 #include <winsock2.h>
46 #undef max
47 #undef min
48 #endif
49 
50 using namespace std;
51 using namespace rc::dynamics;
52 
56 static bool caught_signal = false;
57 void signal_callback_handler(int signum)
58 {
59  printf("Caught signal %d, stopping program!\n", signum);
60  caught_signal = true;
61 }
62 
66 void printUsage(char* arg)
67 {
68  cout << "\nLists available rcdynamics data streams of the specified rc_visard IP, "
69  "\nor requests a data stream and either prints received messages or records "
70  "\nthem as csv-file, see -o option."
71  << "\n\nUsage: \n"
72  << arg << " -v <rcVisardIP> -l | -s <stream> [-a] [-i <networkInterface>]"
73  " [-n <maxNumData>][-t <maxRecTimeSecs>][-o <output_file>]"
74  << endl;
75 }
76 
77 int main(int argc, char* argv[])
78 {
79 #ifdef WIN32
80  WSADATA wsaData;
81  WSAStartup(MAKEWORD(2, 2), &wsaData);
82 #endif
83 
84  // Register signals and signal handler
85  signal(SIGINT, signal_callback_handler);
86  signal(SIGTERM, signal_callback_handler);
87 
91  string out_file_name, visard_ip, network_iface = "", stream_name;
92  unsigned int max_num_recording = 50, max_secs_recording = 5;
93  bool user_autostart = false;
94  bool user_set_out_file = false;
95  bool user_set_max_num_msgs = false;
96  bool user_set_max_recording_time = false;
97  bool user_set_ip = false;
98  bool user_set_stream_type = false;
99  bool only_list_streams = false;
100 
101  int i = 1;
102  while (i < argc)
103  {
104  std::string p = argv[i++];
105 
106  if (p == "-l")
107  {
108  only_list_streams = true;
109  }
110  else if (p == "-s" && i < argc)
111  {
112  stream_name = string(argv[i++]);
113  user_set_stream_type = true;
114  }
115  else if (p == "-a")
116  {
117  user_autostart = true;
118  }
119  else if (p == "-i" && i < argc)
120  {
121  network_iface = string(argv[i++]);
122  }
123  else if (p == "-v" && i < argc)
124  {
125  visard_ip = string(argv[i++]);
126  user_set_ip = true;
127  }
128  else if (p == "-n" && i < argc)
129  {
130  max_num_recording = (unsigned int)std::max(0, atoi(argv[i++]));
131  user_set_max_num_msgs = true;
132  }
133  else if (p == "-t" && i < argc)
134  {
135  max_secs_recording = (unsigned int)std::max(0, atoi(argv[i++]));
136  user_set_max_recording_time = true;
137  }
138  else if (p == "-o" && i < argc)
139  {
140  out_file_name = string(argv[i++]);
141  user_set_out_file = true;
142  }
143  else if (p == "-h")
144  {
145  printUsage(argv[0]);
146  return EXIT_SUCCESS;
147  }
148  else
149  {
150  printUsage(argv[0]);
151  return EXIT_FAILURE;
152  }
153  }
154 
155  if (!user_set_ip)
156  {
157  cerr << "Please specify rc_visard IP." << endl;
158  printUsage(argv[0]);
159  return EXIT_FAILURE;
160  }
161 
162  if (!user_set_stream_type && !only_list_streams)
163  {
164  cerr << "Please specify stream type." << endl;
165  printUsage(argv[0]);
166  return EXIT_FAILURE;
167  }
168 
169  if (!user_set_max_num_msgs && !user_set_max_recording_time)
170  {
171  user_set_max_num_msgs = true;
172  }
173 
177  ofstream output_file;
178  if (user_set_out_file)
179  {
180  output_file.open(out_file_name);
181  if (!output_file.is_open())
182  {
183  cerr << "Could not open file '" << out_file_name << "' for writing!" << endl;
184  return EXIT_FAILURE;
185  }
186  }
187 
191  cout << "connecting to rc_visard " << visard_ip << "..." << endl;
192  auto rc_dynamics = RemoteInterface::create(visard_ip);
193  try {
194  while (!caught_signal && !rc_dynamics->checkSystemReady())
195  {
196  cout << "... system not yet ready. Trying again." << endl;
197  usleep(1000*500);
198  }
199  cout << "... connected!" << endl;
200  } catch (exception &e) {
201  cout << "ERROR! Could not connect to rc_dynamics module on rc_visard: " << e.what() << endl;
202  return EXIT_FAILURE;
203  }
204 
205  /* Only list available streams of device and exit */
206  if (only_list_streams)
207  {
208  auto streams = rc_dynamics->getAvailableStreams();
209  string first_column = "Available streams:";
210  size_t first_column_width = first_column.length();
211  for (auto&& s : streams)
212  if (s.length() > first_column_width)
213  first_column_width = s.length();
214  first_column_width += 5;
215  cout << left << setw(first_column_width) << first_column << "Protobuf message types:" << endl;
216  for (auto&& s : streams)
217  cout << left << setw(first_column_width) << s << rc_dynamics->getPbMsgTypeOfStream(s) << endl;
218  cout << endl << "rc_dynamics is in state: " << rc_dynamics->getDynamicsState();
219  cout << endl << "rc_slam is in state: " << rc_dynamics->getSlamState();
220  cout << endl << "rc_stereo_ins is in state: " << rc_dynamics->getStereoInsState();
221  cout << endl;
222  return EXIT_SUCCESS;
223  }
224 
225  /* For all streams except 'imu' the rc_dynamcis node has to be started */
226  if (user_autostart && stream_name != "imu")
227  {
228  try
229  {
230  cout << "starting SLAM on rc_visard..." << endl;
231  rc_dynamics->startSlam();
232  }
233  catch (exception&)
234  {
235  try
236  {
237  // start the rc::dynamics module on the rc_visard
238  cout << "SLAM not available!" << endl;
239  cout << "starting stereo INS on rc_visard..." << endl;
240  rc_dynamics->start();
241  }
242  catch (exception& e)
243  {
244  cout << "ERROR! Could not start rc_dynamics module on rc_visard: " << e.what() << endl;
245  return EXIT_FAILURE;
246  }
247  }
248  }
249 
253  unsigned int cnt_msgs = 0;
254  try
255  {
256  cout << "Initializing " << stream_name << " data stream..." << endl;
257  auto receiver = rc_dynamics->createReceiverForStream(stream_name, network_iface);
258 
259  unsigned int timeout_millis = 100;
260  receiver->setTimeout(timeout_millis);
261  cout << "Listening for " << stream_name << " messages..." << endl;
262 
263  chrono::time_point<chrono::system_clock> start = chrono::system_clock::now();
264  chrono::duration<double> elapsed_secs(0);
265  while (!caught_signal && (!user_set_max_num_msgs || cnt_msgs < max_num_recording) &&
266  (!user_set_max_recording_time || elapsed_secs.count() < max_secs_recording))
267  {
268  auto msg = receiver->receive(rc_dynamics->getPbMsgTypeOfStream(stream_name));
269  if (msg)
270  {
271  if (output_file.is_open())
272  {
273  if (cnt_msgs == 0)
274  {
275  csv::Header h;
276  output_file << (h << *msg) << endl;
277  }
278  csv::Line l;
279  output_file << (l << *msg) << endl;
280  }
281  else
282  {
283  cout << "received " << stream_name << " msg:" << endl << msg->DebugString() << endl;
284  }
285  ++cnt_msgs;
286  }
287  else
288  {
289  cerr << "did not receive any data during last " << timeout_millis << " ms." << endl;
290  }
291  elapsed_secs = chrono::system_clock::now() - start;
292  }
293  }
294  catch (exception& e)
295  {
296  cout << "Caught exception during streaming, stopping: " << e.what() << endl;
297  }
298 
303  if (user_autostart && stream_name != "imu")
304  {
305  try
306  {
307  cout << "stopping rc_dynamics module on rc_visard..." << endl;
308  rc_dynamics->stop();
309  }
310  catch (exception& e)
311  {
312  cout << "Caught exception: " << e.what() << endl;
313  }
314  }
315 
316  if (output_file.is_open())
317  {
318  output_file.close();
319  cout << "Recorded " << cnt_msgs << " " << stream_name << " messages to '" << out_file_name << "'." << endl;
320  }
321  else
322  {
323  cout << "Received " << cnt_msgs << " " << stream_name << " messages." << endl;
324  }
325 
326 #ifdef WIN32
327  ::WSACleanup();
328 #endif
329 
330  return EXIT_SUCCESS;
331 }
void printUsage(char *arg)
Print usage of example including command line args.
void signal_callback_handler(int signum)
static bool caught_signal
catching signals for proper program escape
struct and methods to "organice" printing of csv-Headers
Definition: csv_printing.h:62
int main(int argc, char *argv[])
struct and methods to "organice" printing of csv-Lines
Definition: csv_printing.h:135


rc_dynamics_api
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Endres
autogenerated on Thu May 9 2019 02:51:36