gc_stream.cc
Go to the documentation of this file.
00001 /*
00002  * This file is part of the rc_genicam_api package.
00003  *
00004  * Copyright (c) 2017 Roboception GmbH
00005  * All rights reserved
00006  *
00007  * Author: Heiko Hirschmueller
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted provided that the following conditions are met:
00011  *
00012  * 1. Redistributions of source code must retain the above copyright notice,
00013  * this list of conditions and the following disclaimer.
00014  *
00015  * 2. Redistributions in binary form must reproduce the above copyright notice,
00016  * this list of conditions and the following disclaimer in the documentation
00017  * and/or other materials provided with the distribution.
00018  *
00019  * 3. Neither the name of the copyright holder nor the names of its contributors
00020  * may be used to endorse or promote products derived from this software without
00021  * specific prior written permission.
00022  *
00023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  * POSSIBILITY OF SUCH DAMAGE.
00034  */
00035 
00036 #include <rc_genicam_api/system.h>
00037 #include <rc_genicam_api/interface.h>
00038 #include <rc_genicam_api/device.h>
00039 #include <rc_genicam_api/stream.h>
00040 #include <rc_genicam_api/buffer.h>
00041 #include <rc_genicam_api/image.h>
00042 #include <rc_genicam_api/config.h>
00043 
00044 #include <rc_genicam_api/pixel_formats.h>
00045 
00046 #include <Base/GCException.h>
00047 
00048 #include <signal.h>
00049 
00050 #include <iostream>
00051 #include <fstream>
00052 #include <iomanip>
00053 #include <algorithm>
00054 #include <atomic>
00055 #include <thread>
00056 #include <chrono>
00057 
00058 #ifdef _WIN32
00059 #undef min
00060 #undef max
00061 #endif
00062 
00063 namespace
00064 {
00065 
00071 std::string ensureNewName(std::string name)
00072 {
00073   // check if given name is already used
00074 
00075   std::ifstream file(name);
00076 
00077   if (file.is_open())
00078   {
00079     file.close();
00080 
00081     // split name in prefix and suffix
00082 
00083     std::string suffix;
00084 
00085     size_t i=name.rfind('.');
00086     if (i != name.npos && name.size()-i <= 4)
00087     {
00088       suffix=name.substr(i);
00089       name=name.substr(0, i);
00090     }
00091 
00092     // add number for finding name that is nor used
00093 
00094     int n=1;
00095     while (n < 100)
00096     {
00097       std::ostringstream s;
00098       s << name << "_" << n << suffix;
00099 
00100       file.open(s.str());
00101       if (!file.is_open())
00102       {
00103         name=s.str();
00104         break;
00105       }
00106 
00107       file.close();
00108       n++;
00109     }
00110   }
00111 
00112   return name;
00113 }
00114 
00119 std::string storeBuffer(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap,
00120                         const std::shared_ptr<GenApi::CChunkAdapter> &chunkadapter,
00121                         const std::string &component, const rcg::Buffer *buffer, uint32_t part)
00122 {
00123   // prepare file name
00124 
00125   std::ostringstream name;
00126 
00127   uint64_t t_sec = buffer->getTimestampNS()/1000000000;
00128   uint64_t t_nsec = buffer->getTimestampNS()%1000000000;
00129 
00130   name << "image_" << t_sec << "." << std::setfill('0') << std::setw(9) << t_nsec;
00131 
00132   if (component.size() > 0)
00133   {
00134     name << '_' << component;
00135   }
00136 
00137   if (chunkadapter)
00138   {
00139     // Append out1 and out2 status to file name: _<out1>_<out2>
00140     std::int64_t line_status=rcg::getInteger(nodemap, "ChunkLineStatusAll");
00141     bool out1 = line_status & 0x01;
00142     bool out2 = line_status & 0x02;
00143     name << "_" << std::noboolalpha << out1 << "_" << out2;
00144   }
00145 
00146   // store image (see e.g. the sv tool of cvkit for show images)
00147 
00148   if (!buffer->getIsIncomplete() && buffer->getImagePresent(part))
00149   {
00150     size_t width=buffer->getWidth(part);
00151     size_t height=buffer->getHeight(part);
00152     const unsigned char *p=static_cast<const unsigned char *>(buffer->getBase(part));
00153 
00154     size_t px=buffer->getXPadding(part);
00155 
00156     uint64_t format=buffer->getPixelFormat(part);
00157     switch (format)
00158     {
00159       case Mono8: // store 8 bit monochrome image
00160       case Confidence8:
00161       case Error8:
00162         {
00163           name << ".pgm";
00164           std::ofstream out(ensureNewName(name.str()), std::ios::binary);
00165 
00166           out << "P5" << std::endl;
00167           out << width << " " << height << std::endl;
00168           out << 255 << "\n";
00169 
00170           std::streambuf *sb=out.rdbuf();
00171 
00172           for (size_t k=0; k<height && out.good(); k++)
00173           {
00174             for (size_t i=0; i<width; i++)
00175             {
00176               sb->sputc(static_cast<char>(*p++));
00177             }
00178 
00179             p+=px;
00180           }
00181 
00182           out.close();
00183         }
00184         break;
00185 
00186       case Coord3D_C16: // store 16 bit monochrome image
00187         {
00188           name << ".pgm";
00189           std::ofstream out(ensureNewName(name.str()), std::ios::binary);
00190 
00191           out << "P5" << std::endl;
00192           out << width << " " << height << std::endl;
00193           out << 65535 << "\n";
00194 
00195           std::streambuf *sb=out.rdbuf();
00196 
00197           // copy image data, pgm is always big endian
00198 
00199           if (buffer->isBigEndian())
00200           {
00201             for (size_t k=0; k<height && out.good(); k++)
00202             {
00203               for (size_t i=0; i<width; i++)
00204               {
00205                 sb->sputc(static_cast<char>(*p++));
00206                 sb->sputc(static_cast<char>(*p++));
00207               }
00208 
00209               p+=px;
00210             }
00211           }
00212           else
00213           {
00214             for (size_t k=0; k<height && out.good(); k++)
00215             {
00216               for (size_t i=0; i<width; i++)
00217               {
00218                 sb->sputc(static_cast<char>(p[1]));
00219                 sb->sputc(static_cast<char>(p[0]));
00220                 p+=2;
00221               }
00222 
00223               p+=px;
00224             }
00225           }
00226 
00227           out.close();
00228         }
00229         break;
00230 
00231       case YCbCr411_8: // convert and store as color image
00232         {
00233           name << ".ppm";
00234           std::ofstream out(ensureNewName(name.str()), std::ios::binary);
00235 
00236           out << "P6" << std::endl;
00237           out << width << " " << height << std::endl;
00238           out << 255 << "\n";
00239 
00240           std::streambuf *sb=out.rdbuf();
00241 
00242           size_t pstep=(width>>2)*6+px;
00243           for (size_t k=0; k<height && out.good(); k++)
00244           {
00245             for (size_t i=0; i<width; i+=4)
00246             {
00247               uint8_t rgb[12];
00248               rcg::convYCbCr411toQuadRGB(rgb, p, static_cast<int>(i));
00249 
00250               for (int j=0; j<12; j++)
00251               {
00252                 sb->sputc(static_cast<char>(rgb[j]));
00253               }
00254             }
00255 
00256             p+=pstep;
00257           }
00258 
00259           out.close();
00260         }
00261         break;
00262 
00263       default:
00264         std::cerr << "storeBuffer(): Unknown pixel format: "
00265                   << GetPixelFormatName(static_cast<PfncFormat>(buffer->getPixelFormat(part)))
00266                   << std::endl;
00267         return std::string();
00268         break;
00269     }
00270   }
00271   else if (buffer->getIsIncomplete())
00272   {
00273     std::cerr << "storeBuffer(): Received incomplete buffer" << std::endl;
00274     return std::string();
00275   }
00276   else if (!buffer->getImagePresent(part))
00277   {
00278     std::cerr << "storeBuffer(): Received buffer without image" << std::endl;
00279     return std::string();
00280   }
00281 
00282   return name.str();
00283 }
00284 
00293 std::string storeBufferAsDisparity(const std::shared_ptr<GenApi::CNodeMapRef> &nodemap,
00294                                    const std::shared_ptr<GenApi::CChunkAdapter> &chunkadapter,
00295                                    const rcg::Buffer *buffer, uint32_t part)
00296 {
00297   std::string dispname;
00298 
00299   if (!buffer->getIsIncomplete() && buffer->getImagePresent(part) &&
00300       buffer->getPixelFormat(part) == Coord3D_C16 && chunkadapter)
00301   {
00302     // get necessary information from ChunkScan3d parameters
00303 
00304     int inv=-1;
00305 
00306     rcg::setString(nodemap, "ChunkComponentSelector", "Disparity");
00307 
00308     if (rcg::getBoolean(nodemap, "ChunkScan3dInvalidDataFlag"))
00309     {
00310       inv=static_cast<int>(rcg::getFloat(nodemap, "ChunkScan3dInvalidDataValue"));
00311     }
00312 
00313     double scale=rcg::getFloat(nodemap, "ChunkScan3dCoordinateScale");
00314     double offset=rcg::getFloat(nodemap, "ChunkScan3dCoordinateOffset");
00315     double f=rcg::getFloat(nodemap, "ChunkScan3dFocalLength");
00316     double t=rcg::getFloat(nodemap, "ChunkScan3dBaseline");
00317     double u=rcg::getFloat(nodemap, "ChunkScan3dPrincipalPointU");
00318     double v=rcg::getFloat(nodemap, "ChunkScan3dPrincipalPointV");
00319 
00320     // proceed if required information is given
00321 
00322     if (scale > 0 && f > 0 && t > 0)
00323     {
00324       // prepare file name
00325 
00326       std::ostringstream name;
00327 
00328       uint64_t t_sec = buffer->getTimestampNS()/1000000000;
00329       uint64_t t_nsec = buffer->getTimestampNS()%1000000000;
00330 
00331       name << "image_" << t_sec << "." << std::setfill('0') << std::setw(9) << t_nsec;
00332 
00333       // convert values and store disparity image
00334 
00335       size_t px=buffer->getXPadding(part);
00336       size_t width=buffer->getWidth(part);
00337       size_t height=buffer->getHeight(part);
00338       const unsigned char *p=static_cast<const unsigned char *>(buffer->getBase(part))+
00339                              2*(width+px)*(height+1);
00340 
00341       name << "_Disparity";
00342 
00343       // Append out1 and out2 status to file name: _<out1>_<out2>
00344       std::int64_t line_status=rcg::getInteger(nodemap, "ChunkLineStatusAll");
00345       bool out1 = line_status & 0x01;
00346       bool out2 = line_status & 0x02;
00347       name << "_" << std::noboolalpha << out1 << "_" << out2;
00348 
00349       dispname=name.str()+".pfm";
00350 
00351       std::ofstream out(ensureNewName(dispname), std::ios::binary);
00352 
00353       out << "Pf" << std::endl;
00354       out << width << " " << height << std::endl;
00355       out << 1 << "\n";
00356 
00357       std::streambuf *sb=out.rdbuf();
00358 
00359       // get 16 bit data, scale and add offset and store as big endian
00360 
00361       bool msbfirst=true;
00362 
00363       {
00364         int pp=1;
00365         char *cc=reinterpret_cast<char *>(&pp);
00366         msbfirst=(cc[0] != 1);
00367       }
00368 
00369       for (size_t k=0; k<height && out.good(); k++)
00370       {
00371         p-=(width+px)<<2;
00372         for (size_t i=0; i<width; i++)
00373         {
00374           int val;
00375           if (buffer->isBigEndian())
00376           {
00377             val=(static_cast<int>(p[0])<<8)|p[1];
00378           }
00379           else
00380           {
00381             val=(static_cast<int>(p[1])<<8)|p[0];
00382           }
00383 
00384           p+=2;
00385 
00386           float d=std::numeric_limits<float>::infinity();
00387           if (val != inv)
00388           {
00389             d=static_cast<float>(val*scale+offset);
00390           }
00391 
00392           char *c=reinterpret_cast<char *>(&d);
00393 
00394           if (msbfirst)
00395           {
00396             sb->sputc(c[0]);
00397             sb->sputc(c[1]);
00398             sb->sputc(c[2]);
00399             sb->sputc(c[3]);
00400           }
00401           else
00402           {
00403             sb->sputc(c[3]);
00404             sb->sputc(c[2]);
00405             sb->sputc(c[1]);
00406             sb->sputc(c[0]);
00407           }
00408 
00409           p+=px;
00410         }
00411       }
00412 
00413       out.close();
00414 
00415       // store parameters that are necessary for 3D reconstruction in separate
00416       // parameter file
00417 
00418       name << "_param.txt";
00419 
00420       out.open(ensureNewName(name.str()));
00421 
00422       out << "# Created by gc_stream" << std::endl;
00423       out << std::fixed << std::setprecision(5);
00424       out << "camera.A=[" << f << " 0 " << u << "; 0 " << f << " " << v << "; 0 0 1]" << std::endl;
00425       out << "camera.height=" << height << std::endl;
00426       out << "camera.width=" << width << std::endl;
00427       out << "rho=" << f*t << std::endl;
00428       out << "t=" << t << std::endl;
00429 
00430       out.close();
00431     }
00432   }
00433 
00434   return dispname;
00435 }
00436 
00437 // simple mechanism to set the boolean flag when the user presses enter in the
00438 // terminal
00439 
00440 std::atomic<bool> user_interrupt(false);
00441 
00442 void interruptHandler(int)
00443 {
00444   std::cout << "Stopping ..." << std::endl;
00445 
00446   user_interrupt=true;
00447 }
00448 
00449 #ifdef _WIN32
00450 
00451 void checkUserInterrupt()
00452 {
00453   char a;
00454   std::cin.get(a);
00455 
00456   std::cout << "Stopping ..." << std::endl;
00457 
00458   user_interrupt=true;
00459 }
00460 
00461 #endif
00462 
00463 }
00464 
00465 int main(int argc, char *argv[])
00466 {
00467   int ret=0;
00468 
00469   signal(SIGINT, interruptHandler);
00470 
00471   try
00472   {
00473     bool store=true;
00474     int i=1;
00475 
00476     if (i < argc)
00477     {
00478       if (std::string(argv[i]) == "-t")
00479       {
00480         store=false;
00481         i++;
00482       }
00483     }
00484 
00485     if (i < argc && std::string(argv[i]) != "-h")
00486     {
00487       // find specific device accross all systems and interfaces and open it
00488 
00489       std::shared_ptr<rcg::Device> dev=rcg::getDevice(argv[i++]);
00490 
00491       if (dev)
00492       {
00493         dev->open(rcg::Device::CONTROL);
00494         std::shared_ptr<GenApi::CNodeMapRef> nodemap=dev->getRemoteNodeMap();
00495 
00496         // get chunk adapter (this switches chunk mode on if possible and
00497         // returns a null pointer if this is not possible)
00498 
00499         std::shared_ptr<GenApi::CChunkAdapter> chunkadapter=rcg::getChunkAdapter(nodemap, dev->getTLType());
00500 
00501         // set values as given on the command line
00502 
00503         int n=1;
00504         while (i < argc)
00505         {
00506           // split argument in key and value
00507 
00508           std::string key=argv[i++];
00509           std::string value;
00510 
00511           size_t k=key.find('=');
00512           if (k != std::string::npos)
00513           {
00514             value=key.substr(k+1);
00515             key=key.substr(0, k);
00516           }
00517 
00518           if (key == "n") // set number of images
00519           {
00520             n=std::max(1, std::stoi(value));
00521           }
00522           else // set key=value pair through GenICam
00523           {
00524             if (value.size() > 0)
00525             {
00526               rcg::setString(nodemap, key.c_str(), value.c_str(), true);
00527             }
00528             else
00529             {
00530               rcg::callCommand(nodemap, key.c_str(), true);
00531             }
00532           }
00533         }
00534 
00535         // print enabled streams
00536 
00537         {
00538           std::vector<std::string> component;
00539 
00540           rcg::getEnum(nodemap, "ComponentSelector", component, false);
00541 
00542           if (component.size() > 0)
00543           {
00544             std::cout << std::endl;
00545             std::cout << "Available components (1 means enabled, 0 means disabled):" << std::endl;
00546             std::cout << std::endl;
00547 
00548             for (size_t k=0; k<component.size(); k++)
00549             {
00550               rcg::setEnum(nodemap, "ComponentSelector", component[k].c_str(), true);
00551 
00552               std::cout << component[k] << ": ";
00553               std::cout << rcg::getBoolean(nodemap, "ComponentEnable", true, true);
00554               std::cout << std::endl;
00555             }
00556 
00557             std::cout << std::endl;
00558           }
00559         }
00560 
00561         // open stream and get n images
00562 
00563         std::vector<std::shared_ptr<rcg::Stream> > stream=dev->getStreams();
00564 
00565         if (stream.size() > 0)
00566         {
00567 #ifdef _WIN32
00568           // start background thread for checking user input
00569           std::thread thread_cui(checkUserInterrupt);
00570           thread_cui.detach();
00571 #endif
00572 
00573           // opening first stream
00574 
00575           stream[0]->open();
00576           stream[0]->startStreaming();
00577 
00578           std::cout << "Package size: " << rcg::getString(nodemap, "GevSCPSPacketSize") << std::endl;
00579 
00580 #ifdef _WIN32
00581           std::cout << "Press 'Enter' to abort grabbing." << std::endl;
00582 #endif
00583           std::cout << std::endl;
00584 
00585           int buffers_received=0;
00586           int buffers_incomplete=0;
00587           auto time_start=std::chrono::steady_clock::now();
00588           double latency_ns=0;
00589 
00590           for (int k=0; k<n && !user_interrupt; k++)
00591           {
00592             // grab next image with timeout of 3 seconds
00593 
00594             int retry=5;
00595             while (retry > 0 && !user_interrupt)
00596             {
00597               const rcg::Buffer *buffer=stream[0]->grab(3000);
00598 
00599               if (buffer != 0)
00600               {
00601                 buffers_received++;
00602 
00603                 if (!buffer->getIsIncomplete())
00604                 {
00605                   // attach buffer to nodemap for accessing chunk data if possible
00606 
00607                   if (chunkadapter)
00608                   {
00609                     chunkadapter->AttachBuffer(
00610                       reinterpret_cast<std::uint8_t *>(buffer->getGlobalBase()),
00611                         static_cast<int64_t>(buffer->getSizeFilled()));
00612                   }
00613 
00614                   // store images in all parts
00615 
00616                   if (store)
00617                   {
00618                     uint32_t npart=buffer->getNumberOfParts();
00619                     for (uint32_t part=0; part<npart; part++)
00620                     {
00621                       if (buffer->getImagePresent(part))
00622                       {
00623                         std::string name;
00624 
00625                         // get component name
00626 
00627                         std::string component=rcg::getComponetOfPart(nodemap, buffer, part);
00628 
00629                         // try storing disparity as float image with meta information
00630 
00631                         if (component == "Disparity")
00632                         {
00633                           name=storeBufferAsDisparity(nodemap, chunkadapter, buffer, part);
00634                         }
00635 
00636                         // otherwise, store as ordinary image
00637 
00638                         if (name.size() == 0)
00639                         {
00640                           name=storeBuffer(nodemap, chunkadapter, component, buffer, part);
00641                         }
00642 
00643                         // report success
00644 
00645                         if (name.size() > 0)
00646                         {
00647                           std::cout << "Image '" << name << "' stored" << std::endl;
00648                           retry=0;
00649                         }
00650                       }
00651                     }
00652                   }
00653                   else
00654                   {
00655                     // just print timestamp of received buffer
00656 
00657                     uint64_t t_sec = buffer->getTimestampNS()/1000000000;
00658                     uint64_t t_nsec = buffer->getTimestampNS()%1000000000;
00659 
00660                     std::cout << "Received buffer with timestamp: " << t_sec << "."
00661                               << std::setfill('0') << std::setw(9) << t_nsec << std::endl;
00662                     retry=0;
00663 
00664                     // accumulate mean latency
00665 
00666                     auto current=std::chrono::system_clock::now();
00667                     latency_ns+=
00668                       static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(current.time_since_epoch()).count())-
00669                       static_cast<double>(buffer->getTimestampNS());
00670                   }
00671 
00672                   // detach buffer from nodemap
00673 
00674                   if (chunkadapter) chunkadapter->DetachBuffer();
00675                 }
00676                 else
00677                 {
00678                   std::cerr << "Incomplete buffer received" << std::endl;
00679                   buffers_incomplete++;
00680                 }
00681               }
00682               else
00683               {
00684                 std::cerr << "Cannot grab images" << std::endl;
00685                 break;
00686               }
00687 
00688               retry--;
00689             }
00690           }
00691 
00692           stream[0]->stopStreaming();
00693           stream[0]->close();
00694 
00695           // report received and incomplete buffers
00696 
00697           std::cout << std::endl;
00698           std::cout << "Received buffers:   " << buffers_received << std::endl;
00699           std::cout << "Incomplete buffers: " << buffers_incomplete << std::endl;
00700 
00701           auto time_stop=std::chrono::steady_clock::now();
00702           std::cout << "Buffers per second: " << std::setprecision(3)
00703                     << 1000.0*buffers_received/std::chrono::duration_cast<std::chrono::milliseconds>(time_stop-time_start).count()
00704                     << std::endl;
00705 
00706           if (!store)
00707           {
00708             if (buffers_received-buffers_incomplete > 0)
00709             {
00710               latency_ns/=buffers_received-buffers_incomplete;
00711             }
00712 
00713             std::cout << "Mean latency:       " << std::setprecision(5) << latency_ns/1.0e6
00714                       << " ms (only meaningful if camera is synchronized e.g. via PTP!)" << std::endl;
00715           }
00716 
00717           // return error code if no images could be received
00718 
00719           if (buffers_incomplete == buffers_received)
00720           {
00721             ret=1;
00722           }
00723         }
00724         else
00725         {
00726           std::cerr << "No streams available" << std::endl;
00727           ret=1;
00728         }
00729 
00730         dev->close();
00731       }
00732       else
00733       {
00734         std::cerr << "Device '" << argv[1] << "' not found!" << std::endl;
00735         ret=1;
00736       }
00737     }
00738     else
00739     {
00740       // show help
00741 
00742       std::cout << argv[0] << " -h | [-t] [<interface-id>:]<device-id> [n=<n>] [<key>=<value>] ..." << std::endl;
00743       std::cout << std::endl;
00744       std::cout << "Stores images from the specified device after applying the given optional GenICam parameters." << std::endl;
00745       std::cout << std::endl;
00746       std::cout << "Options:" << std::endl;
00747       std::cout << "-h   Prints help information and exits" << std::endl;
00748       std::cout << "-t   Testmode, which does not store images and provides extended statistics" << std::endl;
00749       std::cout << std::endl;
00750       std::cout << "Parameters:" << std::endl;
00751       std::cout << "<interface-id> Optional GenICam ID of interface for connecting to the device" << std::endl;
00752       std::cout << "<device-id>    GenICam device ID, serial number or user defined name of device" << std::endl;
00753       std::cout << "n=<n>          Optional number of images to be received (default is 1)" << std::endl;
00754       std::cout << "<key>=<value>  Optional GenICam parameters to be changed in the given order" << std::endl;
00755 #ifdef _WIN32
00756       std::cout << std::endl;
00757       std::cout << "Streaming can be aborted by hitting the 'Enter' key." << std::endl;
00758 #endif
00759       ret=1;
00760     }
00761   }
00762   catch (const std::exception &ex)
00763   {
00764     std::cerr << "Exception: " << ex.what() << std::endl;
00765     ret=2;
00766   }
00767   catch (const GENICAM_NAMESPACE::GenericException &ex)
00768   {
00769     std::cerr << "Exception: " << ex.what() << std::endl;
00770     ret=2;
00771   }
00772   catch (...)
00773   {
00774     std::cerr << "Unknown exception!" << std::endl;
00775     ret=2;
00776   }
00777 
00778   rcg::System::clearSystems();
00779 
00780   return ret;
00781 }


rc_genicam_api
Author(s): Heiko Hirschmueller
autogenerated on Thu Jun 6 2019 18:42:47