SaveImageUtility.cc
Go to the documentation of this file.
1 
37 #ifdef WIN32
38 #ifndef WIN32_LEAN_AND_MEAN
39 #define WIN32_LEAN_AND_MEAN 1
40 #endif
41 
42 #include <windows.h>
43 #include <winsock2.h>
44 #else
45 #include <unistd.h>
46 #include <arpa/inet.h> // htons
47 #endif
48 
49 #include <fstream>
50 #include <iomanip>
51 #include <iostream>
52 #include <limits>
53 #include <sstream>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <signal.h>
57 #include <string.h>
58 #include <string>
59 
61 
64 
65 using namespace crl::multisense;
66 
67 namespace { // anonymous
68 
69 volatile bool doneG = false;
70 
71 struct UserData
72 {
73  Channel *channelP;
74  system::VersionInfo version;
75  system::DeviceInfo deviceInfo;
76  image::Calibration calibration;
77 };
78 
79 void usage(const char *programNameP)
80 {
81  std::cerr << "USAGE: " << programNameP << " [<options>]" << std::endl;
82  std::cerr << "Where <options> are:" << std::endl;
83  std::cerr << "\t-a <current_address> : CURRENT IPV4 address (default=10.66.171.21)" << std::endl;
84  std::cerr << "\t-m <mtu> : MTU to set the camera to (default=7200)" << std::endl;
85  std::cerr << "\t-r <head_id> : remote head ID (default=0)" << std::endl;
86 
87  exit(1);
88 }
89 
90 #ifdef WIN32
91 BOOL WINAPI signalHandler(DWORD dwCtrlType)
92 {
93  CRL_UNUSED (dwCtrlType);
94  doneG = true;
95  return TRUE;
96 }
97 #else
98 void signalHandler(int sig)
99 {
100  (void) sig;
101  doneG = true;
102 }
103 #endif
104 
105 RemoteHeadChannel getRemoteHeadIdFromString(const std::string &head_str)
106 {
107  if (head_str == "VPB")
108  {
109  return Remote_Head_VPB;
110  }
111  else if (head_str == "0")
112  {
113  return Remote_Head_0;
114  }
115  else if (head_str == "1")
116  {
117  return Remote_Head_1;
118  }
119  else if (head_str == "2")
120  {
121  return Remote_Head_2;
122  }
123  else if (head_str == "3")
124  {
125  return Remote_Head_3;
126  }
127 
128  fprintf(stderr, "Error: Unrecognized remote head\n");
129  fprintf(stderr, "Please use one of the following:\n");
130  fprintf(stderr, "\tVPB\n");
131  fprintf(stderr, "\t0'\n");
132  fprintf(stderr, "\t1\n");
133  fprintf(stderr, "\t2\n");
134  fprintf(stderr, "\t3\n");
135  exit(EXIT_FAILURE);
136 }
137 
138 system::DeviceMode getOperatingMode(const std::vector<system::DeviceMode> &modes)
139 {
140  //
141  // Get the full resolution image
142 
143  system::DeviceMode best_mode(0, 0, 0, -1);
144  for (size_t i = 0 ; i < modes.size() ; ++i)
145  {
146  const system::DeviceMode &mode = modes[i];
147  if (mode.width >= best_mode.width && mode.height >= best_mode.height && mode.disparities >= best_mode.disparities) {
148  best_mode = mode;
149  }
150  }
151 
152  //
153  // Target 1/4 of the full res setting. Check to see if there is a setting with a larger number of disparities
154 
155  system::DeviceMode target_mode(best_mode.width / 2, best_mode.height / 2, 0, best_mode.disparities);
156 
157  for (size_t i = 0 ; i < modes.size() ; ++i)
158  {
159  const system::DeviceMode &mode = modes[i];
160  if (mode.width == target_mode.width && mode.height == target_mode.height && mode.disparities >= target_mode.disparities) {
161  target_mode = mode;
162  }
163  }
164 
165  //
166  // The camera does not support our targeted 1/4 res setting
167 
168  if (target_mode.supportedDataSources == 0) {
169  return best_mode;
170  }
171 
172  return target_mode;
173 }
174 
175 
176 std::string writeMatrix(const float* data, size_t width, size_t height)
177 {
178  std::stringstream ss;
179  ss << std::fixed << std::setprecision(6);
180 
181  for (size_t h = 0 ; h < height ; ++h) {
182  for (size_t w = 0 ; w < width ; ++w) {
183  ss << data[w + width * h] << ",";
184  }
185  }
186 
187  return ss.str();
188 }
189 
190 std::string assembledInfoString(const image::Header& header,
191  const system::DeviceInfo& info,
192  const system::VersionInfo& version,
193  const image::Calibration& calibration)
194 {
195  std::stringstream ss;
196 
200 
201  ss << "SN," << info.serialNumber << ",";
202  ss << "HWRev," << info.hardwareRevision << ",";
203  ss << "APIVersion," << version.apiVersion << ",";
204  ss << "FirmwareVersion," << version.sensorFirmwareVersion << ",";
205  ss << "timeSec," << header.timeSeconds << ",";
206  ss << "timeMiroSec," << header.timeMicroSeconds << ",";
207  ss << "exposure," << header.exposure << ",";
208  ss << "gain," << header.gain << ",";
209  ss << "fps," << header.framesPerSecond << ",";
210  ss << "leftM," << writeMatrix(&calibration.left.M[0][0], 3, 3);
211  ss << "leftD," << writeMatrix(calibration.left.D, 8, 1);
212  ss << "leftR," << writeMatrix(&calibration.left.R[0][0], 3, 3);
213  ss << "leftP," << writeMatrix(&calibration.left.P[0][0], 4, 3);
214  ss << "rightM," << writeMatrix(&calibration.right.M[0][0], 3, 3);
215  ss << "rightD," << writeMatrix(calibration.right.D, 8, 1);
216  ss << "rightR," << writeMatrix(&calibration.right.R[0][0], 3, 3);
217  ss << "rightP," << writeMatrix(&calibration.right.P[0][0], 4, 3);
218  if (hasAuxCamera) {
219  ss << "auxM," << writeMatrix(&calibration.aux.M[0][0], 3, 3);
220  ss << "auxD," << writeMatrix(calibration.aux.D, 8, 1);
221  ss << "auxR," << writeMatrix(&calibration.aux.R[0][0], 3, 3);
222  ss << "auxP," << writeMatrix(&calibration.aux.P[0][0], 4, 3);
223  }
224 
225  return ss.str();
226 }
227 
228 bool savePgm(const std::string& fileName,
229  uint32_t width,
230  uint32_t height,
231  uint32_t bitsPerPixel,
232  const std::string& comment,
233  const void *dataP)
234 {
235  std::ofstream outputStream(fileName.c_str(), std::ios::binary | std::ios::out);
236 
237  if (false == outputStream.good()) {
238  std::cerr << "Failed to open \"" << fileName << "\"" << std::endl;
239  return false;
240  }
241 
242  const uint32_t imageSize = height * width;
243 
244  switch(bitsPerPixel) {
245  case 8:
246  {
247 
248  outputStream << "P5\n"
249  << "#" << comment << "\n"
250  << width << " " << height << "\n"
251  << 0xFF << "\n";
252 
253  outputStream.write(reinterpret_cast<const char*>(dataP), imageSize);
254 
255  break;
256  }
257  case 16:
258  {
259  outputStream << "P5\n"
260  << "#" << comment << "\n"
261  << width << " " << height << "\n"
262  << 0xFFFF << "\n";
263 
264  const uint16_t *imageP = reinterpret_cast<const uint16_t*>(dataP);
265 
266  for (uint32_t i=0; i<imageSize; ++i) {
267  uint16_t o = htons(imageP[i]);
268  outputStream.write(reinterpret_cast<const char*>(&o), sizeof(uint16_t));
269  }
270 
271  break;
272  }
273  }
274 
275  outputStream.close();
276  return true;
277 }
278 
279 bool savePgm(const std::string& fileName,
280  const image::Header& header,
281  const system::DeviceInfo& info,
282  const system::VersionInfo& version,
283  const image::Calibration& calibration)
284 {
285  const std::string comment = assembledInfoString(header, info, version, calibration);
286 
287  return savePgm(fileName,
288  header.width,
289  header.height,
290  header.bitsPerPixel,
291  comment,
292  header.imageDataP);
293 }
294 
295 void ppsCallback(const pps::Header& header,
296  void *userDataP)
297 {
298  (void) userDataP;
299  std::cerr << "PPS: " << header.sensorTime << " ns" << std::endl;
300 }
301 
302 void laserCallback(const lidar::Header& header,
303  void *userDataP)
304 {
305  (void) userDataP;
306  std::cerr << "lidar: " << header.pointCount << std::endl;
307 }
308 
309 void imageCallback(const image::Header& header,
310  void *userDataP)
311 {
312  UserData *userData = reinterpret_cast<UserData*>(userDataP);
313 
314  static int64_t lastFrameId = -1;
315 
316  if (-1 == lastFrameId)
317  {
318  savePgm("test.pgm",
319  header,
320  userData->deviceInfo,
321  userData->version,
322  userData->calibration);
323  }
324 
325  lastFrameId = header.frameId;
326 
327  image::Histogram histogram;
328 
329  if (Status_Ok != userData->channelP->getImageHistogram(header.frameId, histogram))
330  std::cerr << "failed to get histogram for frame " << header.frameId << std::endl;
331 }
332 
333 } // anonymous
334 
335 int main(int argc,
336  char **argvPP)
337 {
338  std::string currentAddress = "10.66.171.21";
339  int32_t mtu = 7200;
341 
342 #if WIN32
343  SetConsoleCtrlHandler (signalHandler, TRUE);
344 #else
345  signal(SIGINT, signalHandler);
346 #endif
347 
348  //
349  // Parse args
350 
351  int c;
352 
353  while(-1 != (c = getopt(argc, argvPP, "a:m:r:")))
354  switch(c) {
355  case 'a': currentAddress = std::string(optarg); break;
356  case 'm': mtu = atoi(optarg); break;
357  case 'r': head_id = getRemoteHeadIdFromString(optarg); break;
358  default: usage(*argvPP); break;
359  }
360 
361  //
362  // Initialize communications.
363 
364  Channel *channelP = Channel::Create(currentAddress, head_id);
365  if (NULL == channelP) {
366  std::cerr << "Failed to establish communications with \"" << currentAddress << "\"" << std::endl;
367  return -1;
368  }
369 
370  //
371  // Query version
372 
373  Status status;
375  VersionType version;
376  std::vector<system::DeviceMode> deviceModes;
377  system::DeviceMode operatingMode;
378  image::Calibration calibration;
379  system::DeviceInfo info;
380  UserData userData;
381 
382  status = channelP->getSensorVersion(version);
383  status = channelP->getVersionInfo(v);
384 
385  if (Status_Ok != status) {
386  std::cerr << "Failed to query sensor version: " << Channel::statusString(status) << std::endl;
387  goto clean_out;
388  }
389 
390  std::cout << "API build date : " << v.apiBuildDate << "\n";
391  std::cout << "API version : 0x" << std::hex << std::setw(4) << std::setfill('0') << v.apiVersion << "\n";
392  std::cout << "Firmware build date : " << v.sensorFirmwareBuildDate << "\n";
393  std::cout << "Firmware version : 0x" << std::hex << std::setw(4) << std::setfill('0') << v.sensorFirmwareVersion << "\n";
394  std::cout << "Hardware version : 0x" << std::hex << v.sensorHardwareVersion << "\n";
395  std::cout << "Hardware magic : 0x" << std::hex << v.sensorHardwareMagic << "\n";
396  std::cout << "FPGA DNA : 0x" << std::hex << v.sensorFpgaDna << "\n";
397  std::cout << std::dec;
398 
399  status = channelP->getDeviceModes(deviceModes);
400  if (Status_Ok != status) {
401  std::cerr << "Failed to get device modes: " << Channel::statusString(status) << std::endl;
402  goto clean_out;
403  }
404 
405  operatingMode = getOperatingMode(deviceModes);
406 
407  //
408  // Change framerate
409 
410  {
411  image::Config cfg;
412 
413  status = channelP->getImageConfig(cfg);
414  if (Status_Ok != status) {
415  std::cerr << "Failed to get image config: " << Channel::statusString(status) << std::endl;
416  goto clean_out;
417  } else {
418 
419  std::cout << "Setting resolution to: " << operatingMode.width << "x" <<
420  operatingMode.height << "x" <<
421  operatingMode.disparities << std::endl;
422 
423  cfg.setResolution(operatingMode.width, operatingMode.height);
424  cfg.setDisparities(operatingMode.disparities);
425  cfg.setFps(30.0);
426 
427  status = channelP->setImageConfig(cfg);
428  if (Status_Ok != status) {
429  std::cerr << "Failed to configure sensor: " << Channel::statusString(status) << std::endl;
430  goto clean_out;
431  }
432  }
433  }
434 
435  //
436  // Change MTU
437 
438  status = channelP->setMtu(mtu);
439  if (Status_Ok != status) {
440  std::cerr << "Failed to set MTU to " << mtu << ": " << Channel::statusString(status) << std::endl;
441  goto clean_out;
442  }
443 
444  //
445  // Change trigger source
446 
447  status = channelP->setTriggerSource(Trigger_Internal);
448  if (Status_Ok != status) {
449  std::cerr << "Failed to set trigger source: " << Channel::statusString(status) << std::endl;
450  goto clean_out;
451  }
452 
453  //
454  // Get image Calibration
455 
456  status = channelP->getImageCalibration(calibration);
457  if (Status_Ok != status) {
458  std::cerr << "Failed to get image calibration: " << Channel::statusString(status) << std::endl;
459  goto clean_out;
460  }
461 
462  //
463  // Get device info
464 
465  status = channelP->getDeviceInfo(info);
466  if (Status_Ok != status) {
467  std::cerr << "Failed to get device info: " << Channel::statusString(status) << std::endl;
468  goto clean_out;
469  }
470 
471  userData.channelP = channelP;
472  userData.version = v;
473  userData.deviceInfo = info;
474  userData.calibration = calibration;
475 
476  //
477  // Add callbacks
478 
479  channelP->addIsolatedCallback(imageCallback, Source_All, &userData);
480  channelP->addIsolatedCallback(laserCallback, channelP);
481  channelP->addIsolatedCallback(ppsCallback, channelP);
482 
483  //
484  // Start streaming
485 
486  status = channelP->startStreams((operatingMode.supportedDataSources & Source_Luma_Rectified_Left) |
487  (operatingMode.supportedDataSources & Source_Lidar_Scan));
488  if (Status_Ok != status) {
489  std::cerr << "Failed to start streams: " << Channel::statusString(status) << std::endl;
490  goto clean_out;
491  }
492 
493  while(!doneG)
494  {
495  system::StatusMessage statusMessage;
496  status = channelP->getDeviceStatus(statusMessage);
497 
498  if (Status_Ok == status) {
499  std::cout << "Uptime: " << statusMessage.uptime << ", " <<
500  "SystemOk: " << statusMessage.systemOk << ", " <<
501  "FPGA Temp: " << statusMessage.fpgaTemperature << ", " <<
502  "Left Imager Temp: " << statusMessage.leftImagerTemperature << ", " <<
503  "Right Imager Temp: " << statusMessage.rightImagerTemperature << ", " <<
504  "Input Voltage: " << statusMessage.inputVoltage << ", " <<
505  "Input Current: " << statusMessage.inputCurrent << ", " <<
506  "FPGA Power: " << statusMessage.fpgaPower << ", " <<
507  "Logic Power: " << statusMessage.logicPower << ", " <<
508  "Imager Power: " << statusMessage.imagerPower << std::endl;
509  }
510 
511 
512  usleep(1000000);
513  }
514 
515  status = channelP->stopStreams(Source_All);
516  if (Status_Ok != status) {
517  std::cerr << "Failed to stop streams: " << Channel::statusString(status) << std::endl;
518  }
519 
520 clean_out:
521 
522  Channel::Destroy(channelP);
523  return 0;
524 }
virtual Status startStreams(DataSource mask)=0
static CRL_CONSTEXPR RemoteHeadChannel Remote_Head_VPB
static const char * statusString(Status status)
Definition: channel.cc:802
static CRL_CONSTEXPR TriggerSource Trigger_Internal
virtual Status stopStreams(DataSource mask)=0
static Channel * Create(const std::string &sensorAddress)
Definition: channel.cc:743
int main(int argc, char **argvPP)
void setResolution(uint32_t w, uint32_t h)
std::ostream & writeMatrix(std::ostream &stream, std::string const &name, uint32_t rows, uint32_t columns, T const *data)
static CRL_CONSTEXPR RemoteHeadChannel Remote_Head_0
virtual Status getVersionInfo(system::VersionInfo &v)=0
static CRL_CONSTEXPR RemoteHeadChannel Remote_Head_2
int getopt(int argc, char **argv, char *opts)
Definition: getopt.c:31
static CRL_CONSTEXPR DataSource Source_Lidar_Scan
virtual Status addIsolatedCallback(image::Callback callback, DataSource imageSourceMask, void *userDataP=NULL)=0
#define CRL_UNUSED(var)
Definition: Portability.hh:44
virtual Status setTriggerSource(TriggerSource s)=0
virtual Status getImageCalibration(image::Calibration &c)=0
static CRL_CONSTEXPR uint32_t HARDWARE_REV_MULTISENSE_MONOCAM
virtual Status getDeviceModes(std::vector< system::DeviceMode > &m)=0
static CRL_CONSTEXPR Status Status_Ok
static CRL_CONSTEXPR RemoteHeadChannel Remote_Head_1
virtual Status setMtu(int32_t mtu)=0
virtual Status setImageConfig(const image::Config &c)=0
static CRL_CONSTEXPR uint32_t HARDWARE_REV_MULTISENSE_S30
def usage(progname)
virtual Status getDeviceStatus(system::StatusMessage &status)=0
static CRL_CONSTEXPR uint32_t HARDWARE_REV_MULTISENSE_C6S2_S27
virtual Status getDeviceInfo(system::DeviceInfo &info)=0
static void Destroy(Channel *instanceP)
Definition: channel.cc:789
static CRL_CONSTEXPR RemoteHeadChannel Remote_Head_3
char * optarg
Definition: getopt.c:29
virtual Status getImageConfig(image::Config &c)=0
virtual Status getSensorVersion(VersionType &version)=0
static CRL_CONSTEXPR DataSource Source_All
static CRL_CONSTEXPR DataSource Source_Luma_Rectified_Left


multisense_lib
Author(s):
autogenerated on Sat Jun 24 2023 03:01:21