72 std::cout <<
"gc_stream -h | [-c] [-f <fmt>] [-t] [<interface-id>:]<device-id> [n=<n>] [<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 <<
"<key>=<value> Optional GenICam parameters to be changed in the given order" << std::endl;
88 std::cout << std::endl;
89 std::cout <<
"Streaming can be aborted by hitting the 'Enter' key." << std::endl;
97 std::string getDigitalIO(
const std::shared_ptr<GenApi::CNodeMapRef> &nodemap)
106 std::vector<std::string> io;
109 for (
int i=static_cast<int>(io.size())-1; i>=0; i--)
111 rcg::setEnum(nodemap,
"LineSelector", io[i].c_str(),
true);
115 if (mode ==
"Input") in+=std::to_string((line_status>>i)&0x1);
116 if (mode ==
"Output") out+=std::to_string((line_status>>i)&0x1);
119 if (out.size() > 0 || in.size() > 0)
121 if (out.size() == 0) out.push_back(
'0');
122 if (in.size() == 0) in.push_back(
'0');
125 ret <<
"_" << out <<
"_" << in;
129 catch (
const std::exception &)
134 return std::string();
141 std::string storeBuffer(
rcg::ImgFmt fmt,
const std::shared_ptr<GenApi::CNodeMapRef> &nodemap,
142 const std::string &component,
const rcg::Buffer *buffer, uint32_t part,
143 size_t yoffset=0,
size_t height=0)
152 name <<
"image_" << t_sec <<
"." << std::setfill(
'0') << std::setw(9) << t_nsec;
154 if (component.size() > 0)
156 name <<
'_' << component;
161 name << getDigitalIO(nodemap);
166 std::string full_name;
170 full_name=
storeImage(name.
str(), fmt, image, yoffset, height);
174 std::cerr <<
"storeBuffer(): Received incomplete buffer" << std::endl;
178 std::cerr <<
"storeBuffer(): Received buffer without image" << std::endl;
192 std::string storeBufferAsDisparity(
const std::shared_ptr<GenApi::CNodeMapRef> &nodemap,
195 std::string dispname;
208 inv=
static_cast<int>(
rcg::getFloat(nodemap,
"ChunkScan3dInvalidDataValue"));
211 double scale=
rcg::getFloat(nodemap,
"ChunkScan3dCoordinateScale");
212 double offset=
rcg::getFloat(nodemap,
"ChunkScan3dCoordinateOffset");
221 name <<
"image_" << t_sec <<
"." << std::setfill(
'0') << std::setw(9) << t_nsec;
222 name <<
"_Disparity";
226 name << getDigitalIO(nodemap);
235 std::cerr <<
"storeBuffer(): Received incomplete buffer" << std::endl;
239 std::cerr <<
"storeBuffer(): Received buffer without image" << std::endl;
249 void storeParameter(
const std::shared_ptr<GenApi::CNodeMapRef> &nodemap,
250 const std::string &component,
const rcg::Buffer *buffer,
251 size_t height=0,
bool dispinfo=
false)
262 name <<
"image_" << t_sec <<
"." << std::setfill(
'0') << std::setw(9) << t_nsec;
264 if (component.size() > 0)
266 name <<
'_' << component;
271 name << getDigitalIO(nodemap);
272 name <<
"_param.txt";
276 rcg::setString(nodemap,
"ChunkComponentSelector", component.c_str());
282 double u=
rcg::getFloat(nodemap,
"ChunkScan3dPrincipalPointU");
283 double v=
rcg::getFloat(nodemap,
"ChunkScan3dPrincipalPointV");
284 double exp=
rcg::getFloat(nodemap,
"ChunkExposureTime")/1000000.0;
287 double scale=0, offset=0;
293 inv=
static_cast<int>(
rcg::getFloat(nodemap,
"ChunkScan3dInvalidDataValue"));
297 offset=
rcg::getFloat(nodemap,
"ChunkScan3dCoordinateOffset");
302 if (width > 0 && height > 0 && f > 0 && t > 0)
306 out <<
"# Created by gc_stream" << std::endl;
307 out << std::fixed << std::setprecision(5);
308 out <<
"camera.A=[" << f <<
" 0 " << u <<
"; 0 " << f <<
" " << v <<
"; 0 0 1]" << std::endl;
309 out <<
"camera.height=" << height << std::endl;
310 out <<
"camera.width=" << width << std::endl;
311 out <<
"camera.exposure_time=" << exp << std::endl;
312 out <<
"camera.gain=" << gain << std::endl;
313 out <<
"rho=" << f*t << std::endl;
314 out <<
"t=" << t << std::endl;
318 float v=
static_cast<float>(
rcg::getFloat(nodemap,
"ChunkRcNoise", 0, 0,
true));
319 out <<
"camera.noise=" << v << std::endl;
321 catch (
const std::exception &)
326 float v=
static_cast<float>(
rcg::getFloat(nodemap,
"ChunkRcBrightness", 0, 0,
true));
327 out <<
"camera.brightness=" << v << std::endl;
329 catch (
const std::exception &)
334 float v=
static_cast<float>(
rcg::getFloat(nodemap,
"ChunkRcOut1Reduction", 0, 0,
true));
335 out <<
"camera.out1_reduction=" << v << std::endl;
337 catch (
const std::exception &)
340 for (
int i=0; i<4; i++)
344 rcg::setEnum(nodemap,
"ChunkLineSelector", (
"Out"+std::to_string(i)).c_str(),
true);
345 float v=
static_cast<float>(
rcg::getFloat(nodemap,
"ChunkRcLineRatio", 0, 0,
true));
346 out <<
"camera.out" << i <<
"_ratio=" << v << std::endl;
348 catch (
const std::exception &)
354 out <<
"disp.inv=" << inv << std::endl;
355 out <<
"disp.scale=" << scale << std::endl;
356 out <<
"disp.offset=" << offset << std::endl;
367 std::atomic<bool> user_interrupt(
false);
369 void interruptHandler(
int)
371 std::cout <<
"Stopping ..." << std::endl;
378 void checkUserInterrupt()
383 std::cout <<
"Stopping ..." << std::endl;
392 int main(
int argc,
char *argv[])
396 signal(SIGINT, interruptHandler);
400 bool print_chunk_data=
false;
407 while (i < argc && argv[i][0] ==
'-')
409 std::string param=argv[i];
416 else if (param ==
"-c")
418 print_chunk_data=
true;
421 else if (param ==
"-t")
426 else if (param ==
"-f")
432 std::string imgfmt=argv[i];
437 else if (imgfmt ==
"png")
443 throw std::invalid_argument(std::string(
"Invalid argument of '-f': ")+argv[i]);
450 throw std::invalid_argument(
"Argument expected after '-f'!");
455 throw std::invalid_argument(
"Unknown parameter: "+param);
469 std::shared_ptr<GenApi::CNodeMapRef> nodemap=dev->getRemoteNodeMap();
482 std::string key=argv[i++];
485 size_t k=key.find(
'=');
486 if (k != std::string::npos)
488 value=key.substr(k+1);
489 key=key.substr(0, k);
494 n=std::max(1, std::stoi(value));
498 if (value.size() > 0)
511 if (
rcg::setEnum(nodemap,
"ComponentSelector",
"IntensityCombined",
false) &&
514 if (
rcg::setEnum(nodemap,
"ComponentSelector",
"Intensity",
false) &&
519 std::cout << std::endl;
520 std::cout <<
"NOTE: Disabling component 'Intensity' as 'IntensityCombined' is enabled." 528 std::vector<std::string> component;
530 rcg::getEnum(nodemap,
"ComponentSelector", component,
false);
532 if (component.size() > 0)
534 std::cout << std::endl;
535 std::cout <<
"Available components (1 means enabled, 0 means disabled):" << std::endl;
536 std::cout << std::endl;
538 for (
size_t k=0; k<component.size(); k++)
540 rcg::setEnum(nodemap,
"ComponentSelector", component[k].c_str(),
true);
542 std::cout << component[k] <<
": ";
544 std::cout << std::endl;
547 std::cout << std::endl;
553 std::vector<std::shared_ptr<rcg::Stream> > stream=dev->getStreams();
555 if (stream.size() > 0)
559 std::thread thread_cui(checkUserInterrupt);
566 stream[0]->attachBuffers(
true);
567 stream[0]->startStreaming();
569 std::cout <<
"Package size: " <<
rcg::getString(nodemap,
"GevSCPSPacketSize") << std::endl;
572 std::cout <<
"Press 'Enter' to abort grabbing." << std::endl;
574 std::cout << std::endl;
576 int buffers_received=0;
577 int buffers_incomplete=0;
578 auto time_start=std::chrono::steady_clock::now();
581 for (
int k=0; k<n && !user_interrupt; k++)
586 while (retry > 0 && !user_interrupt)
592 if (buffers_received == 0)
594 time_start=std::chrono::steady_clock::now();
606 for (uint32_t part=0; part<npart; part++)
618 if (component ==
"Disparity" && fmt ==
rcg::PNM)
620 name=storeBufferAsDisparity(nodemap, buffer, part);
622 if (name.size() != 0)
624 std::cout <<
"Image '" << name <<
"' stored" << std::endl;
625 storeParameter(nodemap, component, buffer);
631 if (name.size() == 0)
633 if (component ==
"IntensityCombined")
639 name=storeBuffer(fmt, nodemap,
"Intensity", buffer, part, 0, h2);
643 std::cout <<
"Image '" << name <<
"' stored" << std::endl;
646 name=storeBuffer(fmt, nodemap,
"IntensityRight", buffer, part, h2, h2);
650 std::cout <<
"Image '" << name <<
"' stored" << std::endl;
655 name=storeBuffer(fmt, nodemap, component, buffer, part);
659 std::cout <<
"Image '" << name <<
"' stored" << std::endl;
667 if (component ==
"Intensity")
669 storeParameter(nodemap, component, buffer);
671 else if (component ==
"Disparity")
673 storeParameter(nodemap, component, buffer, 0,
true);
675 else if (component ==
"IntensityCombined")
678 storeParameter(nodemap,
"Intensity", buffer, h2,
false);
698 std::cout <<
"Received buffer with timestamp: " << t_sec <<
"." 699 << std::setfill(
'0') << std::setw(9) << t_nsec << std::endl;
704 auto current=std::chrono::system_clock::now();
706 static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(current.time_since_epoch()).count())-
712 if (print_chunk_data)
714 std::cout << std::endl;
718 std::cout <<
"Cannot find node 'ChunkDataControl'" << std::endl;
721 std::cout << std::endl;
726 std::cerr <<
"Incomplete buffer received" << std::endl;
727 buffers_incomplete++;
732 std::cerr <<
"Cannot grab images" << std::endl;
740 auto time_stop=std::chrono::steady_clock::now();
742 stream[0]->stopStreaming();
747 std::cout << std::endl;
748 std::cout <<
"Received buffers: " << buffers_received << std::endl;
749 std::cout <<
"Incomplete buffers: " << buffers_incomplete << std::endl;
751 std::cout <<
"Buffers per second: " << std::setprecision(3)
752 << 1000.0*buffers_received/std::chrono::duration_cast<std::chrono::milliseconds>(time_stop-time_start).count()
759 if (buffers_received-buffers_incomplete > 0)
761 latency_ns/=buffers_received-buffers_incomplete;
764 std::cout <<
"Mean latency: " << std::setprecision(5) << latency_ns/1.0e6
765 <<
" ms" << std::endl;
771 if (buffers_incomplete == buffers_received)
778 std::cerr <<
"No streams available" << std::endl;
786 std::cerr <<
"Device '" << argv[i] <<
"' not found!" << std::endl;
796 catch (
const std::exception &ex)
798 std::cerr <<
"Exception: " << ex.what() << std::endl;
803 std::cerr <<
"Exception: " << ex.
what() << std::endl;
808 std::cerr <<
"Unknown exception!" << std::endl;
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...
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.
std::shared_ptr< Device > getDevice(const char *id)
Searches across all transport layers and interfaces for a device.
The image class encapsulates image information.
std::string storeImage(const std::string &name, ImgFmt fmt, const Image &image, size_t yoffset, size_t height)
Stores the given image.
bool getContainsChunkdata() const
Returns if the buffer contains chunk data.
int main(int argc, char *argv[])
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.
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.
static void clearSystems()
Clears the internal list of systems.
bool getImagePresent(std::uint32_t part) const
Returns if a 2D, 3D or confidence image is present in the specified part.
The buffer class encapsulates a Genicam buffer that is provided by a stream.
size_t getHeight(std::uint32_t part) const
Returns the height of the image in pixel.
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.
uint64_t getTimestampNS() const
Returns the acquisition timestamp of the data in this buffer in ns.
std::string getComponetOfPart(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const Buffer *buffer, uint32_t ipart)
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.
uint64_t getPixelFormat(std::uint32_t part) const
Returns the pixel format of the specified part as defined in the PFNC.
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.
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.
bool callCommand(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, bool exception)
Calls the given command.
bool getIsIncomplete() const
Signals if the buffer is incomplete due to an error.
GenICam's exception class.
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.
std::uint32_t getNumberOfParts() const
Returns the number of parts, excluding chunk data.
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.
std::string storeImageAsDisparityPFM(const std::string &name, const Image &image, int inv, float scale, float offset)
Stores the given image as disparity.
virtual const char * what() const
Get error description (overwrite from std:exception)