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 #ifdef WIN32
198  Sleep(500);
199 #else
200  usleep(1000*500);
201 #endif
202  }
203  cout << "... connected!" << endl;
204  } catch (exception &e) {
205  cout << "ERROR! Could not connect to rc_dynamics module on rc_visard: " << e.what() << endl;
206  return EXIT_FAILURE;
207  }
208 
209  /* Only list available streams of device and exit */
210  if (only_list_streams)
211  {
212  auto streams = rc_dynamics->getAvailableStreams();
213  string first_column = "Available streams:";
214  size_t first_column_width = first_column.length();
215  for (auto&& s : streams)
216  if (s.length() > first_column_width)
217  first_column_width = s.length();
218  first_column_width += 5;
219  cout << left << setw(first_column_width) << first_column << "Protobuf message types:" << endl;
220  for (auto&& s : streams)
221  cout << left << setw(first_column_width) << s << rc_dynamics->getPbMsgTypeOfStream(s) << endl;
222 
223  cout << endl << "rc_dynamics is in state: " << rc_dynamics->getDynamicsState();
224  cout << endl << "rc_slam is in state: " << rc_dynamics->getSlamState();
225  cout << endl << "rc_stereo_ins is in state: " << rc_dynamics->getStereoInsState() << endl;
226 
227  try {
228  auto cam2imu = rc_dynamics->getCam2ImuTransform();
229  cout << endl << "cam2imu transformation: " << endl << cam2imu.DebugString();
230  } catch (RemoteInterface::NotAvailable& e) {
231  cout << endl << "WARN: Could not retrieve cam2imu transformation from rc_visard. Feature is not available in that image version." << endl;
232  } catch (std::exception &e) {
233  cout << endl << "ERROR: Could not retrieve cam2imu transformation from rc_visard: " << e.what() << endl;
234  }
235  cout << endl;
236  return EXIT_SUCCESS;
237  }
238 
239  /* For all streams except 'imu' the rc_dynamcis node has to be started */
240  if (user_autostart && stream_name != "imu")
241  {
242  try
243  {
244  cout << "starting SLAM on rc_visard..." << endl;
245  rc_dynamics->startSlam();
246  }
247  catch (exception&)
248  {
249  try
250  {
251  // start the rc::dynamics module on the rc_visard
252  cout << "SLAM not available!" << endl;
253  cout << "starting stereo INS on rc_visard..." << endl;
254  rc_dynamics->start();
255  }
256  catch (exception& e)
257  {
258  cout << "ERROR! Could not start rc_dynamics module on rc_visard: " << e.what() << endl;
259  return EXIT_FAILURE;
260  }
261  }
262  }
263 
267  unsigned int cnt_msgs = 0;
268  try
269  {
270  cout << "Initializing " << stream_name << " data stream..." << endl;
271  auto receiver = rc_dynamics->createReceiverForStream(stream_name, network_iface);
272 
273  unsigned int timeout_millis = 100;
274  receiver->setTimeout(timeout_millis);
275  cout << "Listening for " << stream_name << " messages..." << endl;
276 
277  chrono::time_point<chrono::system_clock> start = chrono::system_clock::now();
278  chrono::duration<double> elapsed_secs(0);
279  while (!caught_signal && (!user_set_max_num_msgs || cnt_msgs < max_num_recording) &&
280  (!user_set_max_recording_time || elapsed_secs.count() < max_secs_recording))
281  {
282  auto msg = receiver->receive(rc_dynamics->getPbMsgTypeOfStream(stream_name));
283  if (msg)
284  {
285  if (output_file.is_open())
286  {
287  if (cnt_msgs == 0)
288  {
289  csv::Header h;
290  output_file << (h << *msg) << endl;
291  }
292  csv::Line l;
293  output_file << (l << *msg) << endl;
294  }
295  else
296  {
297  cout << "received " << stream_name << " msg:" << endl << msg->DebugString() << endl;
298  }
299  ++cnt_msgs;
300  }
301  else
302  {
303  cerr << "did not receive any data during last " << timeout_millis << " ms." << endl;
304  }
305  elapsed_secs = chrono::system_clock::now() - start;
306  }
307  }
308  catch (exception& e)
309  {
310  cout << "Caught exception during streaming, stopping: " << e.what() << endl;
311  }
312 
317  if (user_autostart && stream_name != "imu")
318  {
319  try
320  {
321  cout << "stopping rc_dynamics module on rc_visard..." << endl;
322  rc_dynamics->stop();
323  }
324  catch (exception& e)
325  {
326  cout << "Caught exception: " << e.what() << endl;
327  }
328  }
329 
330  if (output_file.is_open())
331  {
332  output_file.close();
333  cout << "Recorded " << cnt_msgs << " " << stream_name << " messages to '" << out_file_name << "'." << endl;
334  }
335  else
336  {
337  cout << "Received " << cnt_msgs << " " << stream_name << " messages." << endl;
338  }
339 
340 #ifdef WIN32
341  ::WSACleanup();
342 #endif
343 
344  return EXIT_SUCCESS;
345 }
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
Thrown if a REST API call is rejected because of 404; i.e. URL not found.


rc_dynamics_api
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Endres
autogenerated on Sat Mar 6 2021 03:53:19