DirectedStreamsUtility.cc
Go to the documentation of this file.
1 
38 #ifdef WIN32
39 #ifndef WIN32_LEAN_AND_MEAN
40 #define WIN32_LEAN_AND_MEAN 1
41 #endif
42 
43 #include <windows.h>
44 #include <winsock2.h>
45 #else
46 #include <unistd.h>
47 #include <arpa/inet.h> // htons
48 #endif
49 
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <signal.h>
53 #include <string.h>
54 #include <string>
55 #include <fstream>
56 #include <iostream>
57 #include <iomanip>
58 
60 
63 
64 using namespace crl::multisense;
65 
66 namespace { // anonymous
67 
68 volatile bool doneG = false;
69 
70 void usage(const char *programNameP)
71 {
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-d <decimation> : Decimation to apply for the directed streams (default=1)" << std::endl;
76 
77  exit(1);
78 }
79 
80 #ifdef WIN32
81 BOOL WINAPI signalHandler(DWORD dwCtrlType)
82 {
83  CRL_UNUSED (dwCtrlType);
84  std::cerr << "Shutting down on signal: CTRL-C" << std::endl;
85  doneG = true;
86  return TRUE;
87 }
88 #else
89 void signalHandler(int sig)
90 {
91  std::cerr << "Shutting down on signal: " << strsignal(sig) << std::endl;
92  doneG = true;
93 }
94 #endif
95 
96 bool savePgm(const std::string& fileName,
97  uint32_t width,
98  uint32_t height,
99  uint32_t bitsPerPixel,
100  const void *dataP)
101 {
102  std::ofstream outputStream(fileName.c_str(), std::ios::binary | std::ios::out);
103 
104  if (false == outputStream.good()) {
105  std::cerr << "Failed to open \"" << fileName << "\"" << std::endl;
106  return false;
107  }
108 
109  const uint32_t imageSize = height * width;
110 
111  switch(bitsPerPixel) {
112  case 8:
113  {
114 
115  outputStream << "P5\n"
116  << width << " " << height << "\n"
117  << 0xFF << "\n";
118 
119  outputStream.write(reinterpret_cast<const char*>(dataP), imageSize);
120 
121  break;
122  }
123  case 16:
124  {
125  outputStream << "P5\n"
126  << width << " " << height << "\n"
127  << 0xFFFF << "\n";
128 
129  const uint16_t *imageP = reinterpret_cast<const uint16_t*>(dataP);
130 
131  for (uint32_t i=0; i<imageSize; ++i) {
132  uint16_t o = htons(imageP[i]);
133  outputStream.write(reinterpret_cast<const char*>(&o), sizeof(uint16_t));
134  }
135 
136  break;
137  }
138  }
139 
140  outputStream.close();
141  return true;
142 }
143 
144 void ppsCallback(const pps::Header& header,
145  void *userDataP)
146 {
147  (void) userDataP;
148  std::cerr << "PPS: " << header.sensorTime << " ns" << std::endl;
149 }
150 
151 void laserCallback(const lidar::Header& header,
152  void *userDataP)
153 {
154  (void) userDataP;
155  double timeStamp = header.timeStartSeconds + 1e-6 * header.timeStartMicroSeconds;
156  static double lastTimeStamp = timeStamp;
157 
158  if (header.scanId % 100 == 0)
159  std::cout << "Laser Frequency " << (1 / (timeStamp - lastTimeStamp)) << std::endl;
160 
161  lastTimeStamp = timeStamp;
162 }
163 
164 void imageCallback(const image::Header& header,
165  void *userDataP)
166 {
167  Channel *channelP = reinterpret_cast<Channel*>(userDataP);
168 
169  double timeStamp = header.timeSeconds + 1e-6 * header.timeMicroSeconds;
170  static double lastTimeStamp = timeStamp;
171 
172  if (header.frameId % 100 == 0)
173  std::cout << "Left Image Frequency " << (1 / (timeStamp - lastTimeStamp)) << " "
174  << "Nominal Frequency " << header.framesPerSecond << std::endl;
175 
176  lastTimeStamp = timeStamp;
177 
178  static int64_t lastFrameId = -1;
179 
180  if (-1 == lastFrameId)
181  savePgm("left_rect.pgm",
182  header.width,
183  header.height,
184  header.bitsPerPixel,
185  header.imageDataP);
186 
187  lastFrameId = header.frameId;
188 
189  image::Histogram histogram;
190 
191  if (Status_Ok != channelP->getImageHistogram(header.frameId, histogram))
192  std::cerr << "failed to get histogram for frame " << header.frameId << std::endl;
193 }
194 
195 void disparityCallback(const image::Header& header,
196  void *userDataP)
197 {
198  Channel *channelP = reinterpret_cast<Channel*>(userDataP);
199 
200  double timeStamp = header.timeSeconds + 1e-6 * header.timeMicroSeconds;
201  static double lastTimeStamp = timeStamp;
202 
203  if (header.frameId % 100 == 0)
204  std::cout << "Disparity Frequency " << (1 / (timeStamp - lastTimeStamp)) << " "
205  << "Nominal Frequency " << header.framesPerSecond << std::endl;
206 
207  lastTimeStamp = timeStamp;
208 
209  static int64_t lastFrameId = -1;
210 
211  if (-1 == lastFrameId)
212  savePgm("disparity.pgm",
213  header.width,
214  header.height,
215  header.bitsPerPixel,
216  header.imageDataP);
217 
218  lastFrameId = header.frameId;
219 
220  image::Histogram histogram;
221 
222  if (Status_Ok != channelP->getImageHistogram(header.frameId, histogram))
223  std::cerr << "failed to get histogram for frame " << header.frameId << std::endl;
224 }
225 
226 } // anonymous
227 
228 int main(int argc,
229  char **argvPP)
230 {
231  std::string currentAddress = "10.66.171.21";
232  int32_t mtu = 7200;
233  uint32_t decimation = 1;
234 
235 #if WIN32
236  SetConsoleCtrlHandler (signalHandler, TRUE);
237 #else
238  signal(SIGINT, signalHandler);
239 #endif
240 
241  //
242  // A directed stream to start
243  DirectedStream stream;
244 
245  //
246  // A vector to store the directed streams query
247  std::vector<DirectedStream> queryStreams;
248 
249  uint32_t streamIndex;
250 
251  //
252  // The port to stream data to
253  uint16_t port;
254 
255  //
256  // Parse args
257 
258  int c;
259 
260  while(-1 != (c = getopt(argc, argvPP, "a:m:d:")))
261  switch(c) {
262  case 'a': currentAddress = std::string(optarg); break;
263  case 'm': mtu = atoi(optarg); break;
264  case 'd': decimation = atoi(optarg); break;
265  default: usage(*argvPP); break;
266  }
267 
268  //
269  // Initialize communications.
270 
271  Channel *channelP = Channel::Create(currentAddress);
272  if (NULL == channelP) {
273  std::cerr << "Failed to establish communications with \"" << currentAddress << "\"" << std::endl;
274  return -1;
275  }
276 
277  //
278  // Query version
279 
280  Status status;
282 
283  status = channelP->getVersionInfo(v);
284  if (Status_Ok != status) {
285  std::cerr << "Failed to query sensor version: " << Channel::statusString(status) << std::endl;
286  goto clean_out;
287  }
288 
289  std::cout << "API build date : " << v.apiBuildDate << "\n";
290  std::cout << "API version : 0x" << std::hex << std::setw(4) << std::setfill('0') << v.apiVersion << "\n";
291  std::cout << "Firmware build date : " << v.sensorFirmwareBuildDate << "\n";
292  std::cout << "Firmware version : 0x" << std::hex << std::setw(4) << std::setfill('0') << v.sensorFirmwareVersion << "\n";
293  std::cout << "Hardware version : 0x" << std::hex << v.sensorHardwareVersion << "\n";
294  std::cout << "Hardware magic : 0x" << std::hex << v.sensorHardwareMagic << "\n";
295  std::cout << "FPGA DNA : 0x" << std::hex << v.sensorFpgaDna << "\n";
296  std::cout << std::dec;
297 
298  //
299  // Change framerate
300 
301  {
302  image::Config cfg;
303 
304  status = channelP->getImageConfig(cfg);
305  if (Status_Ok != status) {
306  std::cerr << "Failed to get image config: " << Channel::statusString(status) << std::endl;
307  goto clean_out;
308  } else {
309 
310  cfg.setResolution(1024, 544);
311  cfg.setFps(30.0);
312 
313  status = channelP->setImageConfig(cfg);
314  if (Status_Ok != status) {
315  std::cerr << "Failed to configure sensor: " << Channel::statusString(status) << std::endl;
316  goto clean_out;
317  }
318  }
319  }
320 
321  //
322  // Change MTU
323 
324  status = channelP->setMtu(mtu);
325  if (Status_Ok != status) {
326  std::cerr << "Failed to set MTU to " << mtu << ": " << Channel::statusString(status) << std::endl;
327  goto clean_out;
328  }
329 
330  //
331  // Change trigger source
332 
333  status = channelP->setTriggerSource(Trigger_Internal);
334  if (Status_Ok != status) {
335  std::cerr << "Failed to set trigger source: " << Channel::statusString(status) << std::endl;
336  goto clean_out;
337  }
338 
339  //
340  // Add callbacks
341 
342  channelP->addIsolatedCallback(imageCallback, Source_Luma_Rectified_Left, channelP);
343  channelP->addIsolatedCallback(disparityCallback, Source_Disparity, channelP);
344  channelP->addIsolatedCallback(laserCallback, channelP);
345  channelP->addIsolatedCallback(ppsCallback, channelP);
346 
347  //
348  // Get the local UDP port
349 
350  status = channelP->getLocalUdpPort(port);
351 
352  //
353  // Start streaming
354 
356 
357  status = channelP->startDirectedStream(stream);
358  if (Status_Ok != status) {
359  std::cerr << "Failed to start streams: " << Channel::statusString(status) << std::endl;
360  goto clean_out;
361  }
362 
363 
364  //
365  // Query all the active directed streams
366 
367  status = channelP->getDirectedStreams(queryStreams);
368 
369  for (streamIndex = 0 ; streamIndex < queryStreams.size() ; ++streamIndex) {
370  std::cout << "Directed Stream " << streamIndex << std::endl;
371  std::cout << "Address: " << queryStreams[streamIndex].address << std::endl;
372  std::cout << "Port: " << std::dec << queryStreams[streamIndex].udpPort << std::endl;
373  std::cout << "Mask: 0x" << std::hex << queryStreams[streamIndex].mask << std::endl;
374  std::cout << "Decimation: " << std::dec << queryStreams[streamIndex].fpsDecimation << std::endl;
375  std::cout << std::endl;
376  }
377 
378  while(!doneG)
379  usleep(100000);
380 
381  //
382  // Stop the directed streams
383 
384  status = channelP->stopDirectedStream(stream);
385  if (Status_Ok != status) {
386  std::cerr << "Failed to stop streams: " << Channel::statusString(status) << std::endl;
387  }
388 
389 clean_out:
390 
391  Channel::Destroy(channelP);
392  return 0;
393 }
virtual Status startDirectedStream(const DirectedStream &stream)=0
static const char * statusString(Status status)
Definition: channel.cc:649
static CRL_CONSTEXPR DataSource Source_Disparity
static CRL_CONSTEXPR TriggerSource Trigger_Internal
ros::Time * timeStamp(M &m)
virtual Status getDirectedStreams(std::vector< DirectedStream > &streams)=0
static Channel * Create(const std::string &sensorAddress)
Definition: channel.cc:623
virtual Status getImageHistogram(int64_t frameId, image::Histogram &histogram)=0
void setResolution(uint32_t w, uint32_t h)
virtual Status stopDirectedStream(const DirectedStream &stream)=0
virtual Status getVersionInfo(system::VersionInfo &v)=0
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
static CRL_CONSTEXPR Status Status_Ok
virtual Status getLocalUdpPort(uint16_t &port)=0
virtual Status setMtu(int32_t mtu)=0
virtual Status setImageConfig(const image::Config &c)=0
int main(int argc, char **argvPP)
def usage(progname)
static void Destroy(Channel *instanceP)
Definition: channel.cc:636
char * optarg
Definition: getopt.c:29
virtual Status getImageConfig(image::Config &c)=0
static CRL_CONSTEXPR DataSource Source_Luma_Rectified_Left


multisense_lib
Author(s):
autogenerated on Sun Mar 14 2021 02:34:50