38 #ifndef WIN32_LEAN_AND_MEAN 39 #define WIN32_LEAN_AND_MEAN 1 46 #include <arpa/inet.h> 68 volatile bool doneG =
false;
70 void usage(
const char *programNameP)
72 std::cerr <<
"USAGE: " << programNameP <<
" [<options>]" << std::endl;
73 std::cerr <<
"Where <options> are:" << std::endl;
74 std::cerr <<
"\t-a <current_address> : CURRENT IPV4 address (default=10.66.171.21)" << std::endl;
75 std::cerr <<
"\t-m <mtu> : CURRENT MTU (default=7200)" << std::endl;
76 std::cerr <<
"\t-d <min_disparity> : CURRENT MINIMUM DISPARITY (default=5.0)" << std::endl;
82 BOOL WINAPI signalHandler(DWORD dwCtrlType)
89 void signalHandler(
int sig)
111 ChannelWrapper(
const std::string &ipAddress):
112 channelPtr_(
Channel::Create(ipAddress))
130 ChannelWrapper(
const ChannelWrapper&) =
delete;
131 ChannelWrapper operator=(
const ChannelWrapper&) =
delete;
133 Channel* channelPtr_ =
nullptr;
139 class ImageBufferWrapper
145 callbackBuffer_(driver->reserveCallbackBuffer()),
150 ~ImageBufferWrapper()
153 driver_->releaseCallbackBuffer(callbackBuffer_);
164 ImageBufferWrapper(
const ImageBufferWrapper&) =
delete;
165 ImageBufferWrapper operator=(
const ImageBufferWrapper&) =
delete;
168 void* callbackBuffer_;
176 std::shared_ptr<const ImageBufferWrapper> disparity =
nullptr;
177 std::shared_ptr<const ImageBufferWrapper> leftRectified =
nullptr;
180 double minDisparity = 0.0;
183 std::vector<WorldPoint> reprojectDisparity(
const std::shared_ptr<const ImageBufferWrapper> disparity,
184 const std::shared_ptr<const ImageBufferWrapper> leftRectified,
189 const size_t width = leftRectified->data().width;
190 const size_t height = leftRectified->data().height;
196 const double xScale = 1.0 / ((
static_cast<double>(deviceInfo.
imagerWidth) /
197 static_cast<double>(width)));
199 const double yScale = 1.0 / ((
static_cast<double>(deviceInfo.
imagerHeight) /
200 static_cast<double>(height)));
210 const double fx = calibration.
left.
P[0][0] * xScale;
211 const double fy = calibration.
left.
P[1][1] * yScale;
212 const double cx = calibration.
left.
P[0][2] * xScale;
213 const double cy = calibration.
left.
P[1][2] * yScale;
214 const double tx = calibration.
right.
P[0][3] / calibration.
left.
P[0][0];
215 const double cxRight = calibration.
right.
P[0][2] * xScale;
217 const uint16_t *disparityP =
reinterpret_cast<const uint16_t*
>(disparity->data().imageDataP);
218 const uint8_t *leftRectifiedP =
reinterpret_cast<const uint8_t*
>(leftRectified->data().imageDataP);
220 std::vector<WorldPoint> points;
221 points.reserve(height * width);
223 for (
size_t h = 0 ; h < height ; ++h) {
224 for (
size_t w = 0 ; w < width ; ++w) {
226 const size_t index = h * width + w;
232 const double d =
static_cast<double>(disparityP[index]) / 16.0;
234 if (d < minDisparity) {
247 const double xB = ((fy * tx) * w) + (-fy * cx * tx);
248 const double yB = ((fx * tx) * h) + (-fx * cy * tx);
249 const double zB = (fx * fy * tx);
250 const double B = (-fy * d) + (fy * (cx - cxRight));
252 points.emplace_back(WorldPoint{xB/B, yB/B, zB/B, leftRectifiedP[index]});
259 bool savePly(
const std::string& fileName,
260 const std::vector<WorldPoint> &points)
262 std::ofstream ply(fileName.c_str());
265 ply <<
"format ascii 1.0\n";
266 ply <<
"element vertex " << points.size() <<
"\n";
267 ply <<
"property float x\n";
268 ply <<
"property float y\n";
269 ply <<
"property float z\n";
270 ply <<
"property uchar red\n";
271 ply <<
"property uchar green\n";
272 ply <<
"property uchar blue\n";
273 ply <<
"end_header\n";
275 for (
const auto &point : points) {
276 const uint32_t luma =
static_cast<uint32_t
>(point.luma);
277 ply << point.x <<
" " << point.y <<
" " << point.z <<
" " << luma <<
" " << luma <<
" " << luma <<
"\n";
286 UserData *userData =
reinterpret_cast<UserData*
>(userDataP);
288 if (!userData->driver) {
289 std::cerr <<
"Invalid MultiSense channel" << std::endl;
296 userData->leftRectified = std::make_shared<ImageBufferWrapper>(userData->driver, header);
297 if (userData->disparity && userData->disparity->data().frameId == header.
frameId) {
308 std::cerr <<
"Unsupported disparity pixel depth" << std::endl;
313 userData->disparity = std::make_shared<ImageBufferWrapper>(userData->driver, header);
314 if (userData->leftRectified && userData->leftRectified->data().frameId == header.
frameId) {
324 std::cerr <<
"Unknown image source: " << header.
source << std::endl;
332 savePly(std::to_string(header.
frameId) +
".ply", reprojectDisparity(userData->disparity,
333 userData->leftRectified,
334 userData->calibration,
335 userData->deviceInfo,
336 userData->minDisparity));
344 std::string currentAddress =
"10.66.171.21";
346 double minDisparity = 5.0;
349 SetConsoleCtrlHandler (signalHandler, TRUE);
351 signal(SIGINT, signalHandler);
359 while(-1 != (c =
getopt(argc, argvPP,
"a:m:d:")))
361 case 'a': currentAddress = std::string(
optarg);
break;
362 case 'm': mtu = atoi(
optarg);
break;
363 case 'd': minDisparity = std::stod(
optarg);
break;
364 default:
usage(*argvPP);
break;
372 auto channelP = std::make_unique<ChannelWrapper>(currentAddress);
373 if (
nullptr == channelP) {
374 std::cerr <<
"Failed to establish communications with \"" << currentAddress <<
"\"" << std::endl;
381 status = channelP->ptr()->setMtu(mtu);
391 status = channelP->ptr()->getImageCalibration(calibration);
401 status = channelP->ptr()->getDeviceInfo(deviceInfo);
412 status = channelP->ptr()->getImageConfig(cfg);
420 status = channelP->ptr()->setImageConfig(cfg);
430 UserData userData{channelP->ptr(),
nullptr,
nullptr, calibration, deviceInfo, minDisparity};
450 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