All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
gc_stream.cc
Go to the documentation of this file.
1 /*
2  * This file is part of the rc_genicam_api package.
3  *
4  * Copyright (c) 2017-2024 Roboception GmbH
5  * All rights reserved
6  *
7  * Author: Heiko Hirschmueller
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 <rc_genicam_api/system.h>
38 #include <rc_genicam_api/device.h>
39 #include <rc_genicam_api/stream.h>
40 #include <rc_genicam_api/buffer.h>
41 #include <rc_genicam_api/image.h>
43 #include <rc_genicam_api/config.h>
45 
47 
48 #include <Base/GCException.h>
49 
50 #include <signal.h>
51 
52 #include <iostream>
53 #include <fstream>
54 #include <iomanip>
55 #include <algorithm>
56 #include <atomic>
57 #include <thread>
58 #include <chrono>
59 
60 #ifdef _WIN32
61 #undef min
62 #undef max
63 #endif
64 
65 namespace
66 {
67 
68 void printHelp()
69 {
70  // show help
71 
72  std::cout << "gc_stream -h | [-c] [-f <fmt>] [-t] [<interface-id>:]<device-id> [n=<n>] [@<file>] [<key>=<value>] ..." << std::endl;
73  std::cout << std::endl;
74  std::cout << "Stores images from the specified device after applying the given optional GenICam parameters." << std::endl;
75  std::cout << std::endl;
76  std::cout << "Options:" << std::endl;
77  std::cout << "-h Prints help information and exits" << std::endl;
78  std::cout << "-c Print ChunkDataControl category for all received buffers" << std::endl;
79  std::cout << "-t Testmode, which does not store images and provides extended statistics" << std::endl;
80  std::cout << "-f pnm|png Format for storing images. Default is pnm" << std::endl;
81  std::cout << std::endl;
82  std::cout << "Parameters:" << std::endl;
83  std::cout << "<interface-id> Optional GenICam ID of interface for connecting to the device" << std::endl;
84  std::cout << "<device-id> GenICam device ID, serial number or user defined name of device" << std::endl;
85  std::cout << "n=<n> Optional number of images to be received (default is 1)" << std::endl;
86  std::cout << "@<file> Optional file with parameters as store with parameter 'gc_info -p ...'" << std::endl;
87  std::cout << "<key>=<value> Optional GenICam parameters to be changed in the given order" << std::endl;
88 #ifdef _WIN32
89  std::cout << std::endl;
90  std::cout << "Streaming can be aborted by hitting the 'Enter' key." << std::endl;
91 #endif
92 }
93 
98 std::string getDigitalIO(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap)
99 {
100  try
101  {
102  int64_t line_status=rcg::getInteger(nodemap, "ChunkLineStatusAll", 0, 0, true);
103 
104  std::string out;
105  std::string in;
106 
107  std::vector<std::string> io;
108  rcg::getEnum(nodemap, "LineSelector", io, true);
109 
110  for (int i=static_cast<int>(io.size())-1; i>=0; i--)
111  {
112  rcg::setEnum(nodemap, "LineSelector", io[i].c_str(), true);
113 
114  std::string mode=rcg::getString(nodemap, "LineMode", true);
115 
116  if (mode == "Input") in+=std::to_string((line_status>>i)&0x1);
117  if (mode == "Output") out+=std::to_string((line_status>>i)&0x1);
118  }
119 
120  if (out.size() > 0 || in.size() > 0)
121  {
122  if (out.size() == 0) out.push_back('0');
123  if (in.size() == 0) in.push_back('0');
124 
125  std::ostringstream ret;
126  ret << "_" << out << "_" << in;
127  return ret.str();
128  }
129  }
130  catch (const std::exception &)
131  {
132  // just ignore and return empty string
133  }
134 
135  return std::string();
136 }
137 
142 std::string storeBuffer(rcg::ImgFmt fmt, const std::shared_ptr<GenApi::CNodeMapRef> &nodemap,
143  const std::string &component, const rcg::Buffer *buffer, uint32_t part,
144  size_t yoffset=0, size_t height=0)
145 {
146  // prepare file name
147 
148  std::ostringstream name;
149 
150  uint64_t t_sec = buffer->getTimestampNS()/1000000000;
151  uint64_t t_nsec = buffer->getTimestampNS()%1000000000;
152 
153  name << "image_" << t_sec << "." << std::setfill('0') << std::setw(9) << t_nsec;
154 
155  if (component.size() > 0)
156  {
157  name << '_' << component;
158  }
159 
160  if (buffer->getContainsChunkdata())
161  {
162  name << getDigitalIO(nodemap);
163  }
164 
165  // store image (see e.g. the sv tool of cvkit for show images)
166 
167  std::string full_name;
168  if (!buffer->getIsIncomplete() && buffer->getImagePresent(part))
169  {
170  rcg::Image image(buffer, part);
171  full_name=storeImage(name.str(), fmt, image, yoffset, height);
172  }
173  else if (buffer->getIsIncomplete())
174  {
175  std::cerr << "storeBuffer(): Received incomplete buffer" << std::endl;
176  }
177  else if (!buffer->getImagePresent(part))
178  {
179  std::cerr << "storeBuffer(): Received buffer without image" << std::endl;
180  }
181 
182  return full_name;
183 }
184 
193 std::string storeBufferAsDisparity(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap,
194  const rcg::Buffer *buffer, uint32_t part)
195 {
196  std::string dispname;
197 
198  if (!buffer->getIsIncomplete() && buffer->getImagePresent(part) &&
199  buffer->getPixelFormat(part) == Coord3D_C16 && buffer->getContainsChunkdata())
200  {
201  // get necessary information from ChunkScan3d parameters
202 
203  int inv=-1;
204 
205  rcg::setString(nodemap, "ChunkComponentSelector", "Disparity");
206 
207  if (rcg::getBoolean(nodemap, "ChunkScan3dInvalidDataFlag"))
208  {
209  inv=static_cast<int>(rcg::getFloat(nodemap, "ChunkScan3dInvalidDataValue"));
210  }
211 
212  double scale=rcg::getFloat(nodemap, "ChunkScan3dCoordinateScale");
213  double offset=rcg::getFloat(nodemap, "ChunkScan3dCoordinateOffset");
214 
215  // prepare file name
216 
217  std::ostringstream name;
218 
219  uint64_t t_sec = buffer->getTimestampNS()/1000000000;
220  uint64_t t_nsec = buffer->getTimestampNS()%1000000000;
221 
222  name << "image_" << t_sec << "." << std::setfill('0') << std::setw(9) << t_nsec;
223  name << "_Disparity";
224 
225  // Append out1 and out2 status to file name: _<out1>_<out2>
226 
227  name << getDigitalIO(nodemap);
228 
229  // store image
230 
231  rcg::Image image(buffer, part);
232  dispname=storeImageAsDisparityPFM(name.str(), image, inv, static_cast<float>(scale), static_cast<float>(offset));
233  }
234  else if (buffer->getIsIncomplete())
235  {
236  std::cerr << "storeBuffer(): Received incomplete buffer" << std::endl;
237  }
238  else if (!buffer->getImagePresent(part))
239  {
240  std::cerr << "storeBuffer(): Received buffer without image" << std::endl;
241  }
242 
243  return dispname;
244 }
245 
250 void storeParameter(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap,
251  const std::string &component, const rcg::Buffer *buffer,
252  size_t height=0, bool dispinfo=false)
253 {
254  if (buffer->getContainsChunkdata())
255  {
256  // prepare file name
257 
258  std::ostringstream name;
259 
260  uint64_t t_sec = buffer->getTimestampNS()/1000000000;
261  uint64_t t_nsec = buffer->getTimestampNS()%1000000000;
262 
263  name << "image_" << t_sec << "." << std::setfill('0') << std::setw(9) << t_nsec;
264 
265  if (component.size() > 0)
266  {
267  name << '_' << component;
268  }
269 
270  // Append out1 and out2 status to file name: _<out1>_<out2>
271 
272  name << getDigitalIO(nodemap);
273  name << "_param.txt";
274 
275  // get 3D parameter
276 
277  rcg::setString(nodemap, "ChunkComponentSelector", component.c_str());
278 
279  int width=static_cast<int>(rcg::getInteger(nodemap, "ChunkWidth"));
280  if (height == 0) height=rcg::getInteger(nodemap, "ChunkHeight");
281  double f=rcg::getFloat(nodemap, "ChunkScan3dFocalLength");
282  double t=rcg::getFloat(nodemap, "ChunkScan3dBaseline");
283  double u=rcg::getFloat(nodemap, "ChunkScan3dPrincipalPointU");
284  double v=rcg::getFloat(nodemap, "ChunkScan3dPrincipalPointV");
285  double exp=rcg::getFloat(nodemap, "ChunkExposureTime")/1000000.0;
286  double gain=rcg::getFloat(nodemap, "ChunkGain");
287  int inv=-1;
288  double scale=0, offset=0;
289 
290  if (dispinfo)
291  {
292  if (rcg::getBoolean(nodemap, "ChunkScan3dInvalidDataFlag"))
293  {
294  inv=static_cast<int>(rcg::getFloat(nodemap, "ChunkScan3dInvalidDataValue"));
295  }
296 
297  scale=rcg::getFloat(nodemap, "ChunkScan3dCoordinateScale");
298  offset=rcg::getFloat(nodemap, "ChunkScan3dCoordinateOffset");
299  }
300 
301  // create parameter file
302 
303  if (width > 0 && height > 0 && f > 0 && t > 0)
304  {
305  std::ofstream out(rcg::ensureNewFileName(name.str()));
306 
307  out << "# Created by gc_stream" << std::endl;
308  out << std::fixed << std::setprecision(5);
309  out << "camera.A=[" << f << " 0 " << u << "; 0 " << f << " " << v << "; 0 0 1]" << std::endl;
310  out << "camera.height=" << height << std::endl;
311  out << "camera.width=" << width << std::endl;
312  out << "camera.exposure_time=" << exp << std::endl;
313  out << "camera.gain=" << gain << std::endl;
314  out << "rho=" << f*t << std::endl;
315  out << "t=" << t << std::endl;
316 
317  try
318  {
319  float v=static_cast<float>(rcg::getFloat(nodemap, "ChunkRcNoise", 0, 0, true));
320  out << "camera.noise=" << v << std::endl;
321  }
322  catch (const std::exception &)
323  { }
324 
325  try
326  {
327  float v=static_cast<float>(rcg::getFloat(nodemap, "ChunkRcBrightness", 0, 0, true));
328  out << "camera.brightness=" << v << std::endl;
329  }
330  catch (const std::exception &)
331  { }
332 
333  try
334  {
335  float v=static_cast<float>(rcg::getFloat(nodemap, "ChunkRcOut1Reduction", 0, 0, true));
336  out << "camera.out1_reduction=" << v << std::endl;
337  }
338  catch (const std::exception &)
339  { }
340 
341  for (int i=0; i<4; i++)
342  {
343  try
344  {
345  rcg::setEnum(nodemap, "ChunkLineSelector", ("Out"+std::to_string(i)).c_str(), true);
346  float v=static_cast<float>(rcg::getFloat(nodemap, "ChunkRcLineRatio", 0, 0, true));
347  out << "camera.out" << i << "_ratio=" << v << std::endl;
348  }
349  catch (const std::exception &)
350  { }
351  }
352 
353  if (scale > 0)
354  {
355  out << "disp.inv=" << inv << std::endl;
356  out << "disp.scale=" << scale << std::endl;
357  out << "disp.offset=" << offset << std::endl;
358  }
359 
360  out.close();
361  }
362  }
363 }
364 
365 // simple mechanism to set the boolean flag when the user presses enter in the
366 // terminal
367 
368 std::atomic<bool> user_interrupt(false);
369 
370 void interruptHandler(int)
371 {
372  std::cout << "Stopping ..." << std::endl;
373 
374  user_interrupt=true;
375 }
376 
377 #ifdef _WIN32
378 
379 void checkUserInterrupt()
380 {
381  char a;
382  std::cin.get(a);
383 
384  std::cout << "Stopping ..." << std::endl;
385 
386  user_interrupt=true;
387 }
388 
389 #endif
390 
391 }
392 
393 int main(int argc, char *argv[])
394 {
395  int ret=0;
396 
397  signal(SIGINT, interruptHandler);
398 
399  try
400  {
401  bool print_chunk_data=false;
402  bool store=true;
403  rcg::ImgFmt fmt=rcg::PNM;
404  int i=1;
405 
406  // get parameters
407 
408  while (i < argc && argv[i][0] == '-')
409  {
410  std::string param=argv[i];
411 
412  if (param == "-h")
413  {
414  printHelp();
415  return 0;
416  }
417  else if (param == "-c")
418  {
419  print_chunk_data=true;
420  i++;
421  }
422  else if (param == "-t")
423  {
424  store=false;
425  i++;
426  }
427  else if (param == "-f")
428  {
429  i++;
430 
431  if (i < argc)
432  {
433  std::string imgfmt=argv[i];
434  if (imgfmt == "pnm")
435  {
436  fmt=rcg::PNM;
437  }
438  else if (imgfmt == "png")
439  {
440  fmt=rcg::PNG;
441  }
442  else
443  {
444  throw std::invalid_argument(std::string("Invalid argument of '-f': ")+argv[i]);
445  }
446 
447  i++;
448  }
449  else
450  {
451  throw std::invalid_argument("Argument expected after '-f'!");
452  }
453  }
454  else
455  {
456  throw std::invalid_argument("Unknown parameter: "+param);
457  }
458  }
459 
460  if (i < argc)
461  {
462  // find specific device accross all systems and interfaces and open it
463 
464  std::shared_ptr<rcg::Device> dev=rcg::getDevice(argv[i]);
465 
466  if (dev)
467  {
468  i++;
469  dev->open(rcg::Device::CONTROL);
470  std::shared_ptr<GenApi::CNodeMapRef> nodemap=dev->getRemoteNodeMap();
471  std::vector<std::pair<std::string, std::string> > chunk_param;
472 
473  // try to enable chunks by default (can be disabed by the user)
474 
475  rcg::setBoolean(nodemap, "ChunkModeActive", true);
476 
477  // set values as given on the command line
478 
479  int n=1;
480  while (i < argc)
481  {
482  std::string key=argv[i++];
483 
484  if (key.size() > 0 && key[0] == '@')
485  {
486  // load streamable parameters from file into nodemap
487 
488  try
489  {
490  rcg::loadStreamableParameters(nodemap, key.substr(1).c_str(), true);
491  }
492  catch (const std::exception &ex)
493  {
494  std::cerr << "Warning: Loading of parameters from file '" << key.substr(1) <<
495  "' failed at least partially" << std::endl;
496  std::cerr << ex.what() << std::endl;
497  }
498  }
499  else
500  {
501  // split argument in key and value
502 
503  std::string value;
504 
505  size_t k=key.find('=');
506  if (k != std::string::npos)
507  {
508  value=key.substr(k+1);
509  key=key.substr(0, k);
510  }
511 
512  if (key == "n") // set number of images
513  {
514  n=std::max(1, std::stoi(value));
515  }
516  else // set key=value pair through GenICam
517  {
518  if (value.size() > 0)
519  {
520  try
521  {
522  rcg::setString(nodemap, key.c_str(), value.c_str(), true);
523  }
524  catch (const std::exception &)
525  {
526  // chunk parameters may fail, try to apply them after
527  // attaching the buffer
528 
529  if (key.compare(0, 5, "Chunk") == 0)
530  {
531  chunk_param.push_back(std::pair<std::string, std::string>(key, value));
532  }
533  else
534  {
535  throw;
536  }
537  }
538  }
539  else
540  {
541  rcg::callCommand(nodemap, key.c_str(), true);
542  }
543  }
544  }
545  }
546 
547  // disable component Intensity if component IntensityCombined is enabled
548 
549  if (rcg::setEnum(nodemap, "ComponentSelector", "IntensityCombined", false) &&
550  rcg::getBoolean(nodemap, "ComponentEnable", true, true))
551  {
552  if (rcg::setEnum(nodemap, "ComponentSelector", "Intensity", false) &&
553  rcg::getBoolean(nodemap, "ComponentEnable", true, true))
554  {
555  rcg::setBoolean(nodemap, "ComponentEnable", false, true);
556 
557  std::cout << std::endl;
558  std::cout << "NOTE: Disabling component 'Intensity' as 'IntensityCombined' is enabled."
559  << std::endl;
560  }
561  }
562 
563  // print enabled streams
564 
565  {
566  std::vector<std::string> component;
567 
568  rcg::getEnum(nodemap, "ComponentSelector", component, false);
569 
570  if (component.size() > 0)
571  {
572  std::cout << std::endl;
573  std::cout << "Available components (1 means enabled, 0 means disabled):" << std::endl;
574  std::cout << std::endl;
575 
576  for (size_t k=0; k<component.size(); k++)
577  {
578  rcg::setEnum(nodemap, "ComponentSelector", component[k].c_str(), true);
579 
580  std::cout << component[k] << ": ";
581  std::cout << rcg::getBoolean(nodemap, "ComponentEnable", true, true);
582  std::cout << std::endl;
583  }
584 
585  std::cout << std::endl;
586  }
587  }
588 
589  // open stream and get n images
590 
591  std::vector<std::shared_ptr<rcg::Stream> > stream=dev->getStreams();
592 
593  if (stream.size() > 0)
594  {
595 #ifdef _WIN32
596  // start background thread for checking user input
597  std::thread thread_cui(checkUserInterrupt);
598  thread_cui.detach();
599 #endif
600 
601  // opening first stream
602 
603  stream[0]->open();
604  stream[0]->attachBuffers(true);
605  stream[0]->startStreaming();
606 
607  std::cout << "Package size: " << rcg::getString(nodemap, "GevSCPSPacketSize") << std::endl;
608 
609 #ifdef _WIN32
610  std::cout << "Press 'Enter' to abort grabbing." << std::endl;
611 #endif
612  std::cout << std::endl;
613 
614  int buffers_received=0;
615  int buffers_incomplete=0;
616  auto time_start=std::chrono::steady_clock::now();
617  double latency_ns=0;
618 
619  for (int k=0; k<n && !user_interrupt; k++)
620  {
621  // grab next image with timeout of 3 seconds
622 
623  int retry=5;
624  while (retry > 0 && !user_interrupt)
625  {
626  const rcg::Buffer *buffer=stream[0]->grab(3000);
627 
628  if (buffer != 0)
629  {
630  if (buffers_received == 0)
631  {
632  time_start=std::chrono::steady_clock::now();
633  }
634 
635  buffers_received++;
636 
637  if (!buffer->getIsIncomplete())
638  {
639  // store images in all parts
640 
641  if (store)
642  {
643  uint32_t npart=buffer->getNumberOfParts();
644  for (uint32_t part=0; part<npart; part++)
645  {
646  if (buffer->getImagePresent(part))
647  {
648  std::string name;
649 
650  // get component name
651 
652  std::string component=rcg::getComponetOfPart(nodemap, buffer, part);
653 
654  // try storing disparity as float image with meta information
655 
656  if (component == "Disparity" && fmt == rcg::PNM)
657  {
658  name=storeBufferAsDisparity(nodemap, buffer, part);
659 
660  if (name.size() != 0)
661  {
662  std::cout << "Image '" << name << "' stored" << std::endl;
663  storeParameter(nodemap, component, buffer);
664  }
665  }
666 
667  // otherwise, store as ordinary image
668 
669  if (name.size() == 0)
670  {
671  if (component == "IntensityCombined" || component == "RawCombined")
672  {
673  // splitting left and right image of combined format of
674  // Roboceptions rc_visard camera
675 
676  std::string comp_name = component.substr(0, component.size() - 8);
677 
678  size_t h2=buffer->getHeight(part)/2;
679  name=storeBuffer(fmt, nodemap, comp_name, buffer, part, 0, h2);
680 
681  if (name.size() > 0)
682  {
683  std::cout << "Image '" << name << "' stored" << std::endl;
684  }
685 
686  name=storeBuffer(fmt, nodemap, comp_name.append("Right"), buffer, part, h2, h2);
687 
688  if (name.size() > 0)
689  {
690  std::cout << "Image '" << name << "' stored" << std::endl;
691  }
692  }
693  else
694  {
695  name=storeBuffer(fmt, nodemap, component, buffer, part);
696 
697  if (name.size() > 0)
698  {
699  std::cout << "Image '" << name << "' stored" << std::endl;
700  }
701  }
702 
703  // store 3D parameters for intensity and disparity
704  // components (nothing is done if chunk parameters are
705  // not available)
706 
707  if (component == "Intensity")
708  {
709  storeParameter(nodemap, component, buffer);
710  }
711  else if (component == "Disparity")
712  {
713  storeParameter(nodemap, component, buffer, 0, true);
714  }
715  else if (component == "IntensityCombined" || component == "RawCombined")
716  {
717  std::string comp_name = component.substr(0, component.size() - 8);
718  size_t h2=buffer->getHeight(part)/2;
719  storeParameter(nodemap, comp_name, buffer, h2, false);
720  }
721  }
722 
723  // report success
724 
725  if (name.size() > 0)
726  {
727  retry=0;
728  }
729  }
730  }
731  }
732  else
733  {
734  // just print timestamp of received buffer
735 
736  uint64_t t_sec = buffer->getTimestampNS()/1000000000;
737  uint64_t t_nsec = buffer->getTimestampNS()%1000000000;
738 
739  std::cout << "Received buffer with timestamp: " << t_sec << "."
740  << std::setfill('0') << std::setw(9) << t_nsec << std::endl;
741  retry=0;
742 
743  // accumulate mean latency
744 
745  auto current=std::chrono::system_clock::now();
746  latency_ns+=
747  static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(current.time_since_epoch()).count())-
748  static_cast<double>(buffer->getTimestampNS());
749  }
750 
751  // optinally print chunk data
752 
753  if (print_chunk_data)
754  {
755  // apply chunk parameters
756 
757  for (size_t i=0; i<chunk_param.size(); i++)
758  {
759  rcg::setString(nodemap, chunk_param[i].first.c_str(),
760  chunk_param[i].second.c_str(), true);
761  }
762 
763  // print chunk data
764 
765  std::cout << std::endl;
766 
767  if (!rcg::printNodemap(nodemap, "ChunkDataControl", 100, false))
768  {
769  std::cout << "Cannot find node 'ChunkDataControl'" << std::endl;
770  }
771 
772  std::cout << std::endl;
773  }
774  }
775  else
776  {
777  std::cerr << "Incomplete buffer received" << std::endl;
778  buffers_incomplete++;
779  }
780  }
781  else
782  {
783  std::cerr << "Cannot grab images" << std::endl;
784  break;
785  }
786 
787  retry--;
788  }
789  }
790 
791  auto time_stop=std::chrono::steady_clock::now();
792 
793  stream[0]->stopStreaming();
794  stream[0]->close();
795 
796  // report received and incomplete buffers
797 
798  std::cout << std::endl;
799  std::cout << "Received buffers: " << buffers_received << std::endl;
800  std::cout << "Incomplete buffers: " << buffers_incomplete << std::endl;
801 
802  std::cout << "Buffers per second: " << std::setprecision(3)
803  << 1000.0*buffers_received/std::chrono::duration_cast<std::chrono::milliseconds>(time_stop-time_start).count()
804  << std::endl;
805 
806  if (!store)
807  {
808  if (rcg::getBoolean(nodemap, "PtpEnable") || rcg::getBoolean(nodemap, "GevIEEE1588"))
809  {
810  if (buffers_received-buffers_incomplete > 0)
811  {
812  latency_ns/=buffers_received-buffers_incomplete;
813  }
814 
815  std::cout << "Mean latency: " << std::setprecision(5) << latency_ns/1.0e6
816  << " ms" << std::endl;
817  }
818  }
819 
820  // return error code if no images could be received
821 
822  if (buffers_incomplete == buffers_received)
823  {
824  ret=1;
825  }
826  }
827  else
828  {
829  std::cerr << "No streams available" << std::endl;
830  ret=1;
831  }
832 
833  dev->close();
834  }
835  else
836  {
837  std::cerr << "Device '" << argv[i] << "' not found!" << std::endl;
838  ret=1;
839  }
840  }
841  else
842  {
843  printHelp();
844  ret=1;
845  }
846  }
847  catch (const std::exception &ex)
848  {
849  std::cerr << "Exception: " << ex.what() << std::endl;
850  ret=2;
851  }
852  catch (const GENICAM_NAMESPACE::GenericException &ex)
853  {
854  std::cerr << "Exception: " << ex.what() << std::endl;
855  ret=2;
856  }
857  catch (...)
858  {
859  std::cerr << "Unknown exception!" << std::endl;
860  ret=2;
861  }
862 
864 
865  return ret;
866 }
rcg::getFloat
double getFloat(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, double *vmin, double *vmax, bool exception, bool igncache)
Get the value of a double feature of the given nodemap.
Definition: config.cc:696
rcg::Buffer::getImagePresent
bool getImagePresent(uint32_t part) const
Returns if a 2D, 3D or confidence image is present in the specified part.
Definition: buffer.cc:472
rcg::Buffer
The buffer class encapsulates a Genicam buffer that is provided by a stream.
Definition: buffer.h:118
rcg::getBoolean
bool getBoolean(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, bool exception, bool igncache)
Get the value of a boolean feature of the given nodemap.
Definition: config.cc:589
rcg::Image
The image class encapsulates image information.
Definition: image.h:55
rcg::getDevice
std::shared_ptr< Device > getDevice(const char *id, uint64_t timeout)
Searches across all transport layers and interfaces for a device.
Definition: device.cc:726
rcg::Buffer::getTimestampNS
uint64_t getTimestampNS() const
Returns the acquisition timestamp of the data in this buffer in ns.
Definition: buffer.cc:670
rcg::Buffer::getNumberOfParts
uint32_t getNumberOfParts() const
Returns the number of parts, excluding chunk data.
Definition: buffer.cc:203
rcg::setBoolean
bool setBoolean(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, bool value, bool exception)
Set the value of a boolean feature of the given nodemap.
Definition: config.cc:107
rcg::Buffer::getIsIncomplete
bool getIsIncomplete() const
Signals if the buffer is incomplete due to an error.
Definition: buffer.cc:315
rcg::Buffer::getContainsChunkdata
bool getContainsChunkdata() const
Returns if the buffer contains chunk data.
Definition: buffer.cc:706
device.h
pixel_formats.h
rcg::ImgFmt
ImgFmt
Definition: image_store.h:46
rcg::storeImage
std::string storeImage(const std::string &name, ImgFmt fmt, const Image &image, size_t yoffset, size_t height)
Stores the given image.
Definition: image_store.cc:567
rcg::storeImageAsDisparityPFM
std::string storeImageAsDisparityPFM(const std::string &name, const Image &image, int inv, float scale, float offset)
Stores the given image as disparity.
Definition: image_store.cc:591
rcg::callCommand
bool callCommand(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, bool exception)
Calls the given command.
Definition: config.cc:61
rcg::Buffer::getHeight
size_t getHeight(uint32_t part) const
Returns the height of the image in pixel.
Definition: buffer.cc:369
rcg::printNodemap
bool printNodemap(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char root[], int depth, bool show_enum_list)
Printing of nodemap, starting at given root node.
Definition: nodemap_out.cc:324
rcg::System::clearSystems
static void clearSystems()
Clears the internal list of systems.
Definition: system.cc:282
rcg::getEnum
std::string getEnum(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, bool exception)
Get the value of an enumeration of the given nodemap.
Definition: config.cc:747
Coord3D_C16
@ Coord3D_C16
Definition: PFNC.h:438
rcg::loadStreamableParameters
bool loadStreamableParameters(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, bool exception)
Load all streamable parameters from file into the nodemap.
Definition: config.cc:1267
interface.h
main
int main(int argc, char *argv[])
Definition: gc_stream.cc:393
GENICAM_NAMESPACE::GenericException::what
virtual const char * what() const
Get error description (overwrite from std:exception)
stream.h
image.h
rcg::Device::CONTROL
@ CONTROL
Definition: device.h:60
buffer.h
rcg::ensureNewFileName
std::string ensureNewFileName(std::string name)
This method checks if the given file name already exists and produces a new file name if this happens...
Definition: image_store.cc:60
GENICAM_NAMESPACE::GenericException
GenICam's exception class.
Definition: GCException.h:63
system.h
config.h
rcg::setString
bool setString(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, const char *value, bool exception)
Set the value of a feature of the given nodemap.
Definition: config.cc:413
std::ostringstream::str
std::string str()
int64_t
__int64 int64_t
Definition: config-win32.h:21
rcg::setEnum
bool setEnum(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, const char *value, bool exception)
Set the value of an enumeration of the given nodemap.
Definition: config.cc:302
std::ostringstream
Definition: Portability.hh:42
width
Definition: Manipulator.hh:15
nodemap_out.h
rcg::getComponetOfPart
std::string getComponetOfPart(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const Buffer *buffer, uint32_t ipart)
Definition: config.cc:1077
image_store.h
rcg::getInteger
int64_t getInteger(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, int64_t *vmin, int64_t *vmax, bool exception, bool igncache)
Get the value of an integer feature of the given nodemap.
Definition: config.cc:634
rcg::getString
std::string getString(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, bool exception, bool igncache)
Get the value of a feature of the given nodemap.
Definition: config.cc:918
GCException.h
rcg::PNM
@ PNM
Definition: image_store.h:46
rcg::Buffer::getPixelFormat
uint64_t getPixelFormat(uint32_t part) const
Returns the pixel format of the specified part as defined in the PFNC.
Definition: buffer.cc:519
rcg::PNG
@ PNG
Definition: image_store.h:46


rc_genicam_api
Author(s): Heiko Hirschmueller
autogenerated on Wed Dec 4 2024 03:10:11