67 void printHelp(
const char *prgname)
71 std::cout << prgname <<
" -h | [-o <output-filename>] [<interface-id>:]<device-id>" << std::endl;
72 std::cout << std::endl;
73 std::cout <<
"Gets the first synchronized image set of the Roboception rc_visard, consisting of left, disparity, confidence and error image, creates a point cloud and stores it in ply ascii format." << std::endl;
74 std::cout << std::endl;
75 std::cout <<
"Options:" << std::endl;
76 std::cout <<
"-h Prints help information and exits" << std::endl;
77 std::cout <<
"-o <file> Set name of output file (default is 'rc_visard_<timestamp>.ply')" << std::endl;
78 std::cout << std::endl;
79 std::cout <<
"Parameters:" << std::endl;
80 std::cout <<
"<interface-id> Optional GenICam ID of interface for connecting to the device" << std::endl;
81 std::cout <<
"<device-id> GenICam device ID, serial number or user defined name of device" << std::endl;
93 inline uint16_t getUint16(
const uint8_t *p,
bool bigendian,
size_t i)
100 ret=
static_cast<uint16_t
>(((p[j]<<8)|p[j+1]));
105 ret=
static_cast<uint16_t
>(((p[j+1]<<8)|p[j]));
130 void storePointCloud(std::string name,
double f,
double t,
double scale,
131 std::shared_ptr<const rcg::Image>
left,
132 std::shared_ptr<const rcg::Image> disp,
133 std::shared_ptr<const rcg::Image> conf=0,
134 std::shared_ptr<const rcg::Image> error=0)
138 size_t width=disp->getWidth();
139 size_t height=disp->getHeight();
140 bool bigendian=disp->isBigEndian();
141 size_t ds=(left->getWidth()+disp->getWidth()-1)/disp->getWidth();
149 const uint8_t *dps=disp->getPixels();
150 size_t dstep=disp->getWidth()*
sizeof(uint16_t)+disp->getXPadding();
156 const uint32_t vinvalid=0xffffffff;
157 std::vector<uint32_t> vindex(width*height);
160 for (
size_t k=0; k<height; k++)
163 for (
size_t i=0; i<width; i++)
166 if ((dps[j]|dps[j+1]) != 0) vindex[vi]=n++;
175 dps=disp->getPixels();
179 const uint16_t vstep=
static_cast<uint16_t
>(std::ceil(2/scale));
182 for (
size_t k=1; k<height; k++)
184 for (
size_t i=1; i<width; i++)
187 v[0]=getUint16(dps, bigendian, i-1);
188 v[1]=getUint16(dps, bigendian, i);
189 v[2]=getUint16(dps+dstep, bigendian, i-1);
190 v[3]=getUint16(dps+dstep, bigendian, i);
196 for (
int jj=0; jj<4; jj++)
200 vmin=std::min(vmin, v[jj]);
201 vmax=std::max(vmax, v[jj]);
206 if (valid >= 3 && vmax-vmin <= vstep)
215 dps=disp->getPixels();
219 const uint8_t *cps=0, *eps=0;
220 size_t cstep=0, estep=0;
224 cps=conf->getPixels();
225 cstep=conf->getWidth()*
sizeof(uint8_t)+conf->getXPadding();
230 eps=error->getPixels();
231 estep=error->getWidth()*
sizeof(uint8_t)+error->getXPadding();
236 if (name.size() == 0)
239 double timestamp=left->getTimestampNS()/1000000000.0;
240 os <<
"rc_visard_" << std::setprecision(16) << timestamp <<
".ply";
244 std::ofstream out(name);
246 out <<
"ply" << std::endl;
247 out <<
"format ascii 1.0" << std::endl;
248 out <<
"comment Created with gc_pointcloud from Roboception GmbH" << std::endl;
249 out <<
"comment Camera [1 0 0; 0 1 0; 0 0 1] [0 0 0]" << std::endl;
250 out <<
"element vertex " << n << std::endl;
251 out <<
"property float32 x" << std::endl;
252 out <<
"property float32 y" << std::endl;
253 out <<
"property float32 z" << std::endl;
254 out <<
"property float32 scan_size" << std::endl;
258 out <<
"property float32 scan_conf" << std::endl;
263 out <<
"property float32 scan_error" << std::endl;
266 out <<
"property uint8 diffuse_red" << std::endl;
267 out <<
"property uint8 diffuse_green" << std::endl;
268 out <<
"property uint8 diffuse_blue" << std::endl;
269 out <<
"element face " << tn << std::endl;
270 out <<
"property list uint8 uint32 vertex_indices" << std::endl;
271 out <<
"end_header" << std::endl;
275 for (
size_t k=0; k<height; k++)
277 for (
size_t i=0; i<width; i++)
281 double d=scale*getUint16(dps, bigendian, i);
289 double x=(i+0.5-0.5*width)*t/d;
290 double y=(k+0.5-0.5*height)*t/d;
295 double x2=(i-0.5*width)*t/d;
301 rcg::getColor(rgb, left, static_cast<uint32_t>(ds), static_cast<uint32_t>(i),
302 static_cast<uint32_t>(k));
306 out << x <<
" " << y <<
" " << z <<
" " << size <<
" ";
310 out << cps[i]/255.0 <<
" ";
315 out << eps[i]*scale*f*t/(d*d) <<
" ";
318 out << static_cast<int>(rgb[0]) <<
" ";
319 out << static_cast<int>(rgb[1]) <<
" ";
320 out << static_cast<int>(rgb[2]) << std::endl;
329 dps=disp->getPixels();
333 uint32_t *ips=vindex.data();
334 for (
size_t k=1; k<height; k++)
336 for (
size_t i=1; i<width; i++)
339 v[0]=getUint16(dps, bigendian, i-1);
340 v[1]=getUint16(dps, bigendian, i);
341 v[2]=getUint16(dps+dstep, bigendian, i-1);
342 v[3]=getUint16(dps+dstep, bigendian, i);
348 for (
int jj=0; jj<4; jj++)
352 vmin=std::min(vmin, v[jj]);
353 vmax=std::max(vmax, v[jj]);
358 if (valid >= 3 && vmax-vmin <= vstep)
363 if (ips[i-1] != vinvalid)
368 if (ips[width+i-1] != vinvalid)
370 fc[j++]=ips[width+i-1];
373 if (ips[width+i] != vinvalid)
375 fc[j++]=ips[width+i];
378 if (ips[i] != vinvalid)
383 out <<
"3 " << fc[0] <<
' ' << fc[1] <<
' ' << fc[2] << std::endl;
387 out <<
"3 " << fc[2] <<
' ' << fc[3] <<
' ' << fc[0] << std::endl;
401 int main(
int argc,
char *argv[])
415 if (std::string(argv[i]) ==
"-o")
422 std::cout <<
"Unknown parameter: " << argv[i] << std::endl;
423 std::cout << std::endl;
431 if (i >= argc || std::string(argv[i]) ==
"-h")
444 std::shared_ptr<GenApi::CNodeMapRef> nodemap=dev->getRemoteNodeMap();
449 std::shared_ptr<GenApi::CChunkAdapter> chunkadapter=
rcg::getChunkAdapter(nodemap, dev->getTLType());
453 double f=
rcg::getFloat(nodemap,
"FocalLengthFactor", 0, 0,
false);
455 double scale=
rcg::getFloat(nodemap,
"Scan3dCoordinateScale", 0, 0,
true);
474 std::string linesource=
rcg::getEnum(nodemap,
"LineSource",
true);
475 std::string filter=
rcg::getEnum(nodemap,
"AcquisitionAlternateFilter",
true);
477 if (linesource ==
"ExposureAlternateActive" && filter ==
"OnlyLow")
482 catch (
const std::exception &)
496 rcg::setEnum(nodemap,
"PixelFormat",
"YCbCr411_8",
false);
502 std::vector<std::string> component;
504 rcg::getEnum(nodemap,
"ComponentSelector", component,
true);
506 for (
size_t k=0; k<component.size(); k++)
508 rcg::setEnum(nodemap,
"ComponentSelector", component[k].c_str(),
true);
510 bool enable=(component[k] ==
"Intensity" || component[k] ==
"Disparity" ||
511 component[k] ==
"Confidence" || component[k] ==
"Error");
519 rcg::setString(nodemap,
"AcquisitionMultiPartMode",
"SynchronizedComponents");
523 std::vector<std::shared_ptr<rcg::Stream> > stream=dev->getStreams();
525 if (stream.size() > 0)
530 stream[0]->startStreaming();
541 int async=0, maxasync=50;
543 while (run && async < maxasync)
560 chunkadapter->AttachBuffer(
568 for (uint32_t part=0; part<partn; part++)
579 if (component ==
"Intensity")
581 left_list.
add(buffer, part);
584 else if (component ==
"Disparity")
586 disp_list.
add(buffer, part);
589 else if (component ==
"Confidence")
591 conf_list.
add(buffer, part);
594 else if (component ==
"Error")
596 error_list.
add(buffer, part);
603 std::shared_ptr<const rcg::Image> left=left_list.
find(timestamp, left_tol);
604 std::shared_ptr<const rcg::Image> disp=disp_list.
find(timestamp, disp_tol);
609 std::shared_ptr<const rcg::Image> conf;
610 std::shared_ptr<const rcg::Image> error;
614 conf=conf_list.
find(disp->getTimestampNS());
615 error=error_list.
find(disp->getTimestampNS());
618 if (left && disp && conf && error)
622 storePointCloud(name, f, t, scale, left, disp, conf, error);
643 if (chunkadapter) chunkadapter->DetachBuffer();
648 std::cerr <<
"Cannot grab images" << std::endl;
655 if (async >= maxasync && run)
657 std::cerr <<
"Cannot grab synchronized left and disparity image" << std::endl;
663 stream[0]->stopStreaming();
668 std::cerr <<
"No streams available" << std::endl;
678 std::cerr <<
"Device '" << argv[1] <<
"' not found!" << std::endl;
682 catch (
const std::exception &ex)
684 std::cerr << ex.what() << std::endl;
689 std::cerr <<
"Exception: " << ex.
what() << std::endl;
694 std::cerr <<
"Unknown exception!" << std::endl;
std::shared_ptr< Device > getDevice(const char *id)
Searches across all transport layers and interfaces for a device.
size_t getSizeFilled() const
Returns the number of bytes written into the buffer last time it has been filled. ...
std::shared_ptr< GenApi::CChunkAdapter > getChunkAdapter(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const std::string &tltype)
Sets ChunkModeActive to 1, creates a chunk adapter for the specified transport layer and attaches it ...
std::shared_ptr< const Image > find(uint64_t timestamp) const
Returns the image that has the given timestamp.
An object of this class manages a limited number of images.
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.
void removeOld(uint64_t timestamp)
Removes all images that have a timestamp that is older or equal than the given timestamp.
The buffer class encapsulates a Genicam buffer that is provided by a stream.
void * getGlobalBase() const
Returns the global base address of the buffer memory.
void checkFeature(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, const char *value, bool igncache)
Checks the value of given feature and throws an exception in case of a mismatch.
LOG4CPP_EXPORT CategoryStream & left(CategoryStream &os)
left manipulator
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.
void add(const std::shared_ptr< const Image > &image)
Adds the given image to the internal list.
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.
void getColor(uint8_t rgb[3], const std::shared_ptr< const rcg::Image > &img, uint32_t ds, uint32_t i, uint32_t k)
Expects an image in Mono8 or YCbCr411_8 format and returns the color as RGB value at the given pixel ...
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.
uint64_t getTimestampNS() const
Returns the acquisition timestamp of the data in this buffer in ns.
bool getImagePresent(std::uint32_t part) const
Returns if a 2D, 3D or confidence image is present in the specified part.
bool getIsIncomplete() const
Signals if the buffer is incomplete due to an error.
GenICam's exception class.
int main(int argc, char *argv[])
std::string getComponetOfPart(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const rcg::Buffer *buffer, uint32_t ipart)
virtual const char * what() const
Get error description (overwrite from std:exception)
std::uint32_t getNumberOfParts() const
Returns the number of parts, excluding chunk data.