38 #ifndef WIN32_LEAN_AND_MEAN 39 #define WIN32_LEAN_AND_MEAN 1 46 #include <arpa/inet.h> 69 volatile bool doneG =
false;
71 void usage(
const char *programNameP)
73 std::cerr <<
"USAGE: " << programNameP <<
" [<options>]" << std::endl;
74 std::cerr <<
"Where <options> are:" << std::endl;
75 std::cerr <<
"\t-a <current_address> : CURRENT IPV4 address (default=10.66.171.21)" << std::endl;
76 std::cerr <<
"\t-m <mtu> : CURRENT MTU (default=7200)" << std::endl;
77 std::cerr <<
"\t-d <min_disparity> : CURRENT MINIMUM DISPARITY (default=5.0)" << std::endl;
83 BOOL WINAPI signalHandler(DWORD dwCtrlType)
90 void signalHandler(
int sig)
112 ChannelWrapper(
const std::string &ipAddress):
113 channelPtr_(
Channel::Create(ipAddress))
131 ChannelWrapper(
const ChannelWrapper&) =
delete;
132 ChannelWrapper operator=(
const ChannelWrapper&) =
delete;
134 Channel* channelPtr_ =
nullptr;
140 class ImageBufferWrapper
146 callbackBuffer_(driver->reserveCallbackBuffer()),
151 ~ImageBufferWrapper()
154 driver_->releaseCallbackBuffer(callbackBuffer_);
165 ImageBufferWrapper(
const ImageBufferWrapper&) =
delete;
166 ImageBufferWrapper operator=(
const ImageBufferWrapper&) =
delete;
169 void* callbackBuffer_;
177 std::shared_ptr<const ImageBufferWrapper> disparity =
nullptr;
178 std::shared_ptr<const ImageBufferWrapper> leftRectified =
nullptr;
181 double minDisparity = 0.0;
184 std::vector<WorldPoint> reprojectDisparity(
const std::shared_ptr<const ImageBufferWrapper> disparity,
185 const std::shared_ptr<const ImageBufferWrapper> leftRectified,
190 const size_t width = leftRectified->data().width;
191 const size_t height = leftRectified->data().height;
197 const double xScale = 1.0 / ((
static_cast<double>(deviceInfo.
imagerWidth) /
198 static_cast<double>(width)));
200 const double yScale = 1.0 / ((
static_cast<double>(deviceInfo.
imagerHeight) /
201 static_cast<double>(height)));
211 const double fx = calibration.
left.
P[0][0] * xScale;
212 const double fy = calibration.
left.
P[1][1] * yScale;
213 const double cx = calibration.
left.
P[0][2] * xScale;
214 const double cy = calibration.
left.
P[1][2] * yScale;
215 const double tx = calibration.
right.
P[0][3] / calibration.
right.
P[0][0];
216 const double cxRight = calibration.
right.
P[0][2] * xScale;
218 const uint16_t *disparityP =
reinterpret_cast<const uint16_t*
>(disparity->data().imageDataP);
219 const uint8_t *leftRectifiedP =
reinterpret_cast<const uint8_t*
>(leftRectified->data().imageDataP);
221 std::vector<WorldPoint> points;
222 points.reserve(height * width);
224 for (
size_t h = 0 ; h < height ; ++h) {
225 for (
size_t w = 0 ; w < width ; ++w) {
227 const size_t index = h * width + w;
233 const double d =
static_cast<double>(disparityP[index]) / 16.0;
235 if (d < minDisparity) {
248 const double xB = ((fy * tx) * w) + (-fy * cx * tx);
249 const double yB = ((fx * tx) * h) + (-fx * cy * tx);
250 const double zB = (fx * fy * tx);
251 const double invB = 1. / (-fy * d) + (fy * (cx - cxRight));
253 points.emplace_back(WorldPoint{
static_cast<float>(xB * invB),
254 static_cast<float>(yB * invB),
255 static_cast<float>(zB * invB),
256 leftRectifiedP[index]});
263 bool savePly(
const std::string& fileName,
264 const std::vector<WorldPoint> &points)
266 std::stringstream ss;
269 ss <<
"format ascii 1.0\n";
270 ss <<
"element vertex " << points.size() <<
"\n";
271 ss <<
"property float x\n";
272 ss <<
"property float y\n";
273 ss <<
"property float z\n";
274 ss <<
"property uchar red\n";
275 ss <<
"property uchar green\n";
276 ss <<
"property uchar blue\n";
277 ss <<
"end_header\n";
279 for (
const auto &point : points) {
280 const uint32_t luma =
static_cast<uint32_t
>(point.luma);
281 ss << point.x <<
" " << point.y <<
" " << point.z <<
" " << luma <<
" " << luma <<
" " << luma <<
"\n";
284 std::ofstream ply(fileName.c_str());
293 UserData *userData =
reinterpret_cast<UserData*
>(userDataP);
295 if (!userData->driver) {
296 std::cerr <<
"Invalid MultiSense channel" << std::endl;
303 userData->leftRectified = std::make_shared<ImageBufferWrapper>(userData->driver, header);
304 if (userData->disparity && userData->disparity->data().frameId == header.
frameId) {
315 std::cerr <<
"Unsupported disparity pixel depth" << std::endl;
320 userData->disparity = std::make_shared<ImageBufferWrapper>(userData->driver, header);
321 if (userData->leftRectified && userData->leftRectified->data().frameId == header.
frameId) {
331 std::cerr <<
"Unknown image source: " << header.
source << std::endl;
339 std::cout <<
"Saving pointcloud for image header " << header.
frameId << std::endl;
340 savePly(std::to_string(header.
frameId) +
".ply", reprojectDisparity(userData->disparity,
341 userData->leftRectified,
342 userData->calibration,
343 userData->deviceInfo,
344 userData->minDisparity));
352 std::string currentAddress =
"10.66.171.21";
354 double minDisparity = 5.0;
357 SetConsoleCtrlHandler (signalHandler, TRUE);
359 signal(SIGINT, signalHandler);
367 while(-1 != (c =
getopt(argc, argvPP,
"a:m:d:")))
369 case 'a': currentAddress = std::string(
optarg);
break;
370 case 'm': mtu = atoi(
optarg);
break;
371 case 'd': minDisparity = std::stod(
optarg);
break;
372 default:
usage(*argvPP);
break;
380 auto channelP = std::make_unique<ChannelWrapper>(currentAddress);
381 if (
nullptr == channelP ||
nullptr == channelP->ptr()) {
382 std::cerr <<
"Failed to establish communications with \"" << currentAddress <<
"\"" << std::endl;
389 status = channelP->ptr()->setMtu(mtu);
399 status = channelP->ptr()->getImageCalibration(calibration);
409 status = channelP->ptr()->getDeviceInfo(deviceInfo);
420 status = channelP->ptr()->getImageConfig(cfg);
428 status = channelP->ptr()->setImageConfig(cfg);
438 UserData userData{channelP->ptr(),
nullptr,
nullptr, calibration, deviceInfo, minDisparity};
458 status = channelP->ptr()->stopStreams(
Source_All);
static CRL_CONSTEXPR DataSource Source_Disparity_Left
static const char * statusString(Status status)
void setResolution(uint32_t w, uint32_t h)
int getopt(int argc, char **argv, char *opts)
static CRL_CONSTEXPR Status Status_Ok
int main(int argc, char **argvPP)
static void Destroy(Channel *instanceP)
static CRL_CONSTEXPR DataSource Source_All
static CRL_CONSTEXPR DataSource Source_Luma_Rectified_Left