38 #ifndef WIN32_LEAN_AND_MEAN
39 #define WIN32_LEAN_AND_MEAN 1
46 #include <arpa/inet.h>
64 #include <MultiSense/MultiSenseChannel.hh>
70 volatile bool doneG =
false;
72 void usage(
const char *programNameP)
74 std::cerr <<
"USAGE: " << programNameP <<
" [<options>]" << std::endl;
75 std::cerr <<
"Where <options> are:" << std::endl;
76 std::cerr <<
"\t-a <current_address> : CURRENT IPV4 address (default=10.66.171.21)" << std::endl;
77 std::cerr <<
"\t-m <mtu> : CURRENT MTU (default=1500)" << std::endl;
78 std::cerr <<
"\t-d <min_disparity> : CURRENT MINIMUM DISPARITY (default=5.0)" << std::endl;
84 BOOL WINAPI signalHandler(DWORD dwCtrlType)
91 void signalHandler(
int sig)
109 std::shared_ptr<const ImageBufferWrapper> disparity =
nullptr;
110 std::shared_ptr<const ImageBufferWrapper> leftRectified =
nullptr;
113 double minDisparity = 0.0;
116 std::vector<WorldPoint> reprojectDisparity(
const std::shared_ptr<const ImageBufferWrapper> &disparity,
117 const std::shared_ptr<const ImageBufferWrapper> &leftRectified,
122 const size_t width = leftRectified->data().width;
123 const size_t height = leftRectified->data().height;
129 const double xScale = 1.0 / ((
static_cast<double>(deviceInfo.
imagerWidth) /
130 static_cast<double>(width)));
132 const double yScale = 1.0 / ((
static_cast<double>(deviceInfo.
imagerHeight) /
133 static_cast<double>(height)));
143 const double fx = calibration.
left.
P[0][0] * xScale;
144 const double fy = calibration.
left.
P[1][1] * yScale;
145 const double cx = calibration.
left.
P[0][2] * xScale;
146 const double cy = calibration.
left.
P[1][2] * yScale;
147 const double tx = calibration.
right.
P[0][3] / calibration.
right.
P[0][0];
148 const double cxRight = calibration.
right.
P[0][2] * xScale;
150 const uint16_t *disparityP =
reinterpret_cast<const uint16_t*
>(disparity->data().imageDataP);
151 const uint8_t *leftRectifiedP =
reinterpret_cast<const uint8_t*
>(leftRectified->data().imageDataP);
153 std::vector<WorldPoint> points;
154 points.reserve(height * width);
156 for (
size_t h = 0 ; h < height ; ++h) {
157 for (
size_t w = 0 ; w < width ; ++w) {
159 const size_t index = h * width + w;
165 const double d =
static_cast<double>(disparityP[index]) / 16.0;
167 if (d < minDisparity) {
180 const double xB = ((fy * tx) * w) + (-fy * cx * tx);
181 const double yB = ((fx * tx) * h) + (-fx * cy * tx);
182 const double zB = (fx * fy * tx);
183 const double invB = 1. / (-fy *
d) + (fy * (cx - cxRight));
185 points.emplace_back(WorldPoint{
static_cast<float>(xB * invB),
186 static_cast<float>(yB * invB),
187 static_cast<float>(zB * invB),
188 leftRectifiedP[index]});
195 bool savePly(
const std::string& fileName,
196 const std::vector<WorldPoint> &points)
198 std::stringstream ss;
201 ss <<
"format ascii 1.0\n";
202 ss <<
"element vertex " << points.size() <<
"\n";
203 ss <<
"property float x\n";
204 ss <<
"property float y\n";
205 ss <<
"property float z\n";
206 ss <<
"property uchar red\n";
207 ss <<
"property uchar green\n";
208 ss <<
"property uchar blue\n";
209 ss <<
"end_header\n";
211 for (
const auto &point : points) {
212 const uint32_t luma =
static_cast<uint32_t
>(point.luma);
213 ss << point.x <<
" " << point.y <<
" " << point.z <<
" " << luma <<
" " << luma <<
" " << luma <<
"\n";
216 std::ofstream ply(fileName.c_str());
225 UserData *userData =
reinterpret_cast<UserData*
>(userDataP);
227 if (!userData->driver) {
228 std::cerr <<
"Invalid MultiSense channel" << std::endl;
235 userData->leftRectified = std::make_shared<ImageBufferWrapper>(userData->driver, header);
236 if (userData->disparity && userData->disparity->data().frameId ==
header.frameId) {
246 if (
header.bitsPerPixel != 16) {
247 std::cerr <<
"Unsupported disparity pixel depth" << std::endl;
252 userData->disparity = std::make_shared<ImageBufferWrapper>(userData->driver, header);
253 if (userData->leftRectified && userData->leftRectified->data().frameId ==
header.frameId) {
263 std::cerr <<
"Unknown image source: " <<
header.source << std::endl;
271 std::cout <<
"Saving pointcloud for image header " <<
header.frameId << std::endl;
273 userData->leftRectified,
274 userData->calibration,
275 userData->deviceInfo,
276 userData->minDisparity));
284 std::string currentAddress =
"10.66.171.21";
286 double minDisparity = 5.0;
289 SetConsoleCtrlHandler (signalHandler, TRUE);
291 signal(SIGINT, signalHandler);
299 while(-1 != (c =
getopt(argc, argvPP,
"a:m:d:")))
301 case 'a': currentAddress = std::string(
optarg);
break;
302 case 'm': mtu = atoi(
optarg);
break;
303 case 'd': minDisparity = std::stod(
optarg);
break;
304 default:
usage(*argvPP);
break;
312 auto channelP = std::make_unique<ChannelWrapper>(currentAddress);
313 if (
nullptr == channelP ||
nullptr == channelP->ptr()) {
314 std::cerr <<
"Failed to establish communications with \"" << currentAddress <<
"\"" << std::endl;
321 status = channelP->ptr()->setMtu(mtu);
323 status = channelP->ptr()->setBestMtu();
333 status = channelP->ptr()->getImageCalibration(calibration);
343 status = channelP->ptr()->getDeviceInfo(deviceInfo);
354 status = channelP->ptr()->getImageConfig(cfg);
362 status = channelP->ptr()->setImageConfig(cfg);
372 UserData userData{channelP->ptr(),
nullptr,
nullptr, calibration, deviceInfo, minDisparity};
392 status = channelP->ptr()->stopStreams(
Source_All);