MRPT  1.9.9
CCameraSensor.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "hwdrivers-precomp.h" // Precompiled headers
11 
12 #include <mrpt/system/os.h>
15 #include <mrpt/system/filesystem.h>
18 #include <mrpt/obs/CSensoryFrame.h>
19 #include <mrpt/obs/CRawlog.h>
22 #include <mrpt/gui/WxUtils.h>
23 #include <mrpt/gui/WxSubsystem.h>
25 
26 using namespace mrpt;
27 using namespace mrpt::hwdrivers;
28 using namespace mrpt::gui;
29 using namespace mrpt::obs;
30 using namespace mrpt::config;
31 using namespace mrpt::system;
32 using namespace mrpt::io;
33 using namespace mrpt::serialization;
34 using namespace mrpt::img;
35 using namespace std;
36 using namespace std::literals;
37 
39 
40 /* -----------------------------------------------------
41  Constructor
42  ----------------------------------------------------- */
44  : mrpt::system::COutputLogger("CCameraSensor"),
45  m_sensorPose(),
46  m_grabber_type("opencv"),
47  m_capture_grayscale(false),
48  m_cv_camera_index(0),
49  m_cv_camera_type("CAMERA_CV_AUTODETECT"),
50  m_cv_options(),
51  // ---
52  m_dc1394_camera_guid(0),
53  m_dc1394_camera_unit(0),
54  m_dc1394_options(),
55  m_preview_decimation(0),
56  m_preview_reduction(1),
57  // ---
58  m_bumblebee_dc1394_camera_guid(0),
59  m_bumblebee_dc1394_camera_unit(0),
60  m_bumblebee_dc1394_framerate(15),
61  // ---
62  m_svs_camera_index(0),
63  m_svs_options(),
64  // ---
65  m_sr_open_from_usb(true),
66  m_sr_save_3d(true),
67  m_sr_save_range_img(true),
68  m_sr_save_intensity_img(true),
69  m_sr_save_confidence(true),
70  // ---
71  m_kinect_save_3d(
72  true), // These options are also used for OpenNI2 grabber
73  m_kinect_save_range_img(true),
74  m_kinect_save_intensity_img(true),
75  m_kinect_video_rgb(true),
76  // ---
77  m_fcs_start_synch_capture(false),
78  // ---
79  m_img_dir_url(""),
80  m_img_dir_left_format("imL_%04d.jpg"),
81  m_img_dir_right_format("imR_%04d.jpg"),
82  m_img_dir_start_index(0),
83  m_img_dir_end_index(100),
84  m_img_dir_is_stereo(true),
85  m_img_dir_counter(0),
86  // ---
87  m_external_images_own_thread(false),
88  m_camera_grab_decimator(0),
89  m_camera_grab_decimator_counter(0),
90  m_preview_counter(0),
91  m_external_image_saver_count(std::thread::hardware_concurrency()),
92  m_threadImagesSaverShouldEnd(false),
93  m_hook_pre_save(nullptr),
94  m_hook_pre_save_param(nullptr)
95 {
96  m_sensorLabel = "CAMERA";
98 }
99 
100 /* -----------------------------------------------------
101  initialize
102  ----------------------------------------------------- */
104 {
105  cout << "[CCameraSensor::initialize] Opening camera..." << endl;
106  close();
107 
108  // Select type of device
109  m_grabber_type = trim(lowerCase(m_grabber_type));
110  m_cv_camera_type = trim(upperCase(m_cv_camera_type));
111 
112  if (m_grabber_type == "opencv")
113  {
114  // OpenCV driver:
115  TCameraType ct;
116  try
117  {
119  m_cv_camera_type);
120  }
121  catch (std::exception&)
122  {
123  m_state = CGenericSensor::ssError;
124  throw;
125  }
126  cout << format(
127  "[CCameraSensor::initialize] opencv camera, index: %i type: "
128  "%i...\n",
129  int(m_cv_camera_index), (int)ct);
130  m_cap_cv.reset(
131  new CImageGrabber_OpenCV(m_cv_camera_index, ct, m_cv_options));
132 
133  if (!m_cap_cv->isOpen())
134  {
135  m_state = CGenericSensor::ssError;
137  "[CCameraSensor::initialize] ERROR: Couldn't open OpenCV "
138  "camera.")
139  }
140  }
141  else if (m_grabber_type == "dc1394")
142  {
143  // m_cap_dc1394
144  cout << format(
145  "[CCameraSensor::initialize] dc1394 camera, GUID: 0x%lX "
146  "UNIT:%d...\n",
147  long(m_dc1394_camera_guid), m_dc1394_camera_unit);
148  m_cap_dc1394.reset(new CImageGrabber_dc1394(
149  m_dc1394_camera_guid, m_dc1394_camera_unit, m_dc1394_options,
150  true /* verbose */));
151 
152  if (!m_cap_dc1394->isOpen())
153  {
154  m_state = CGenericSensor::ssError;
156  "[CCameraSensor::initialize] ERROR: Couldn't open dc1394 "
157  "camera.")
158  }
159  }
160  else if (m_grabber_type == "bumblebee_dc1394")
161  {
162  cout << format(
163  "[CCameraSensor::initialize] bumblebee_libdc1394 camera: "
164  "GUID:0x%08X Index:%i FPS:%f...\n",
165  (unsigned int)(m_bumblebee_dc1394_camera_guid),
166  m_bumblebee_dc1394_camera_unit, m_bumblebee_dc1394_framerate);
167  m_cap_bumblebee_dc1394.reset(new CStereoGrabber_Bumblebee_libdc1394(
168  m_bumblebee_dc1394_camera_guid, m_bumblebee_dc1394_camera_unit,
169  m_bumblebee_dc1394_framerate));
170  }
171  else if (m_grabber_type == "svs")
172  {
173  cout << format(
174  "[CCameraSensor::initialize] SVS camera: %u...\n",
175  (unsigned int)(m_svs_camera_index));
176  m_cap_svs.reset(
177  new CStereoGrabber_SVS(m_svs_camera_index, m_svs_options));
178  }
179  else if (m_grabber_type == "ffmpeg")
180  {
181  // m_cap_ffmpeg
182  cout << format(
183  "[CCameraSensor::initialize] FFmpeg stream: %s...\n",
184  m_ffmpeg_url.c_str());
185  m_cap_ffmpeg.reset(new CFFMPEG_InputStream());
186 
187  if (!m_cap_ffmpeg->openURL(m_ffmpeg_url, m_capture_grayscale))
188  {
189  m_state = CGenericSensor::ssError;
191  "Error opening FFmpeg stream: %s", m_ffmpeg_url.c_str())
192  }
193  }
194  else if (m_grabber_type == "swissranger")
195  {
196  cout << "[CCameraSensor::initialize] SwissRanger camera...\n";
197  m_cap_swissranger.reset(new CSwissRanger3DCamera());
198 
199  m_cap_swissranger->setOpenFromUSB(m_sr_open_from_usb);
200  m_cap_swissranger->setOpenIPAddress(m_sr_ip_address);
201 
202  m_cap_swissranger->setSave3D(m_sr_save_3d);
203  m_cap_swissranger->setSaveRangeImage(m_sr_save_range_img);
204  m_cap_swissranger->setSaveIntensityImage(m_sr_save_intensity_img);
205  m_cap_swissranger->setSaveConfidenceImage(m_sr_save_confidence);
206 
207  if (!m_path_for_external_images.empty())
208  m_cap_swissranger->setPathForExternalImages(
209  m_path_for_external_images);
210 
211  // Open it:
212  try
213  {
214  m_cap_swissranger
215  ->initialize(); // This will launch an exception if needed.
216  }
217  catch (std::exception&)
218  {
219  m_state = CGenericSensor::ssError;
220  throw;
221  }
222  }
223  else if (m_grabber_type == "kinect")
224  {
225  cout << "[CCameraSensor::initialize] Kinect camera...\n";
226  m_cap_kinect.reset(new CKinect());
227  m_cap_kinect->enableGrab3DPoints(m_kinect_save_3d);
228  m_cap_kinect->enableGrabDepth(m_kinect_save_range_img);
229  m_cap_kinect->enableGrabRGB(m_kinect_save_intensity_img);
230  m_cap_kinect->setVideoChannel(
231  m_kinect_video_rgb ? CKinect::VIDEO_CHANNEL_RGB
233 
234  if (!m_path_for_external_images.empty())
235  m_cap_kinect->setPathForExternalImages(m_path_for_external_images);
236 
237  // Open it:
238  try
239  {
240  m_cap_kinect
241  ->initialize(); // This will launch an exception if needed.
242  }
243  catch (std::exception&)
244  {
245  m_state = CGenericSensor::ssError;
246  throw;
247  }
248  }
249  else if (m_grabber_type == "openni2")
250  {
251  cout << "[CCameraSensor::initialize] OpenNI2 sensor...\n";
252  m_cap_openni2.reset(new COpenNI2Sensor());
253  m_cap_openni2->enableGrab3DPoints(m_kinect_save_3d); // It uses the
254  // same options as
255  // the Kinect
256  // grabber
257  m_cap_openni2->enableGrabDepth(m_kinect_save_range_img);
258  m_cap_openni2->enableGrabRGB(m_kinect_save_intensity_img);
259 
260  if (!m_path_for_external_images.empty())
261  m_cap_openni2->setPathForExternalImages(m_path_for_external_images);
262 
263  // Open it:
264  try
265  {
266  m_cap_openni2
267  ->initialize(); // This will launch an exception if needed.
268  }
269  catch (std::exception& e)
270  {
271  m_state = CGenericSensor::ssError;
272  throw e;
273  }
274  }
275  else if (m_grabber_type == "image_dir")
276  {
277  // m_cap_image_dir
278  cout << format(
279  "[CCameraSensor::initialize] Image dir: %s...\n",
280  m_img_dir_url.c_str());
281  m_cap_image_dir.reset(new std::string());
282  }
283  else if (m_grabber_type == "rawlog")
284  {
285  // m_cap_rawlog
286  cout << format(
287  "[CCameraSensor::initialize] Rawlog stream: %s...\n",
288  m_rawlog_file.c_str());
289  m_cap_rawlog.reset(new CFileGZInputStream());
290 
291  if (!m_cap_rawlog->open(m_rawlog_file))
292  {
293  m_state = CGenericSensor::ssError;
295  "Error opening rawlog file: %s", m_rawlog_file.c_str())
296  }
297  // File open OK.
298  // Localize the external images directory of this rawlog, if it exists:
299  m_rawlog_detected_images_dir =
300  CRawlog::detectImagesDirectory(m_rawlog_file);
301  }
302  else if (m_grabber_type == "flycap")
303  {
304  cout << "[CCameraSensor::initialize] PGR FlyCapture2 camera...\n";
305  try
306  {
307  // Open camera and start capture:
308  m_cap_flycap.reset(new CImageGrabber_FlyCapture2(m_flycap_options));
309  }
310  catch (std::exception&)
311  {
312  m_state = CGenericSensor::ssError;
313  throw;
314  }
315  }
316  else if (m_grabber_type == "flycap_stereo")
317  {
318  cout
319  << "[CCameraSensor::initialize] PGR FlyCapture2 stereo camera...\n";
320  try
321  {
322  // Open camera and start capture:
323  m_cap_flycap_stereo_l.reset(new CImageGrabber_FlyCapture2());
324  m_cap_flycap_stereo_r.reset(new CImageGrabber_FlyCapture2());
325 
326  cout << "[CCameraSensor::initialize] PGR FlyCapture2 stereo "
327  "camera: Opening LEFT camera...\n";
328  m_cap_flycap_stereo_l->open(
329  m_flycap_stereo_options[0], false /* don't start grabbing */);
330 
331  cout << "[CCameraSensor::initialize] PGR FlyCapture2 stereo "
332  "camera: Opening RIGHT camera...\n";
333  m_cap_flycap_stereo_r->open(
334  m_flycap_stereo_options[1], false /* don't start grabbing */);
335 
336  // Now, start grabbing "simultaneously":
337  if (m_fcs_start_synch_capture)
338  {
339  const CImageGrabber_FlyCapture2* cams[2] = {
340  m_cap_flycap_stereo_l.get(), m_cap_flycap_stereo_r.get()};
342  }
343  else
344  {
345  m_cap_flycap_stereo_l->startCapture();
346  m_cap_flycap_stereo_r->startCapture();
347  }
348  }
349  catch (std::exception&)
350  {
351  m_state = CGenericSensor::ssError;
352  throw;
353  }
354  }
355  else if (m_grabber_type == "duo3d")
356  {
357  // m_cap_duo3D
358  cout << format("[CCameraSensor::initialize] DUO3D stereo camera ...\n");
359 
360  // Open it:
361  try
362  {
363  m_cap_duo3d.reset(new CDUO3DCamera(m_duo3d_options));
364  }
365  catch (std::exception& e)
366  {
367  m_state = CGenericSensor::ssError;
368  throw e;
369  }
370  }
371  else
373  "Unknown 'grabber_type' found: %s", m_grabber_type.c_str())
374 
375  // Change state:
376  cout << "[CCameraSensor::initialize] Done!" << endl;
377  m_state = CGenericSensor::ssWorking;
378 
379  // Launch independent thread?
380  if (m_external_images_own_thread)
381  {
382  m_threadImagesSaverShouldEnd = false;
383 
384  m_threadImagesSaver.clear();
385  m_threadImagesSaver.resize(m_external_image_saver_count);
386 
387  m_toSaveList.clear();
388  m_toSaveList.resize(m_external_image_saver_count);
389 
390  for (unsigned int i = 0; i < m_external_image_saver_count; ++i)
391  m_threadImagesSaver[i] =
392  std::thread(&CCameraSensor::thread_save_images, this, i);
393  }
394 }
395 
396 /* -----------------------------------------------------
397  close
398  ----------------------------------------------------- */
400 {
401  m_cap_cv.reset();
402  m_cap_dc1394.reset();
403  m_cap_flycap.reset();
404  m_cap_flycap_stereo_l.reset();
405  m_cap_flycap_stereo_r.reset();
406  m_cap_bumblebee_dc1394.reset();
407  m_cap_ffmpeg.reset();
408  m_cap_rawlog.reset();
409  m_cap_swissranger.reset();
410  m_cap_kinect.reset();
411  m_cap_svs.reset();
412  m_cap_image_dir.reset();
413  m_cap_duo3d.reset();
414 
416 
417  // Wait for threads:
418  if (!m_threadImagesSaver.empty())
419  {
420  m_threadImagesSaverShouldEnd = true;
421  for (size_t i = 0; i < m_threadImagesSaver.size(); i++)
422  m_threadImagesSaver[i].join();
423  }
424 }
425 
426 /* -----------------------------------------------------
427  loadConfig_sensorSpecific
428  ----------------------------------------------------- */
430  const mrpt::config::CConfigFileBase& configSource,
431  const std::string& iniSection)
432 {
433  // At this point, my parent class CGenericSensor has already loaded its
434  // params:
435  // Since cameras are special, we'll take control over "m_grab_decimation"
436  // so
437  // external image files are not saved just to be discarded later on...
438  if (m_grab_decimation > 0)
439  {
440  m_camera_grab_decimator = m_grab_decimation;
441  m_camera_grab_decimator_counter = 0;
442  // Reset in parent:
443  m_grab_decimation = 0;
444  }
445  else
446  m_camera_grab_decimator = m_camera_grab_decimator_counter = 0;
447 
448  m_grabber_type = configSource.read_string_first_word(
449  iniSection, "grabber_type", m_grabber_type);
451  preview_decimation, int, m_preview_decimation, configSource, iniSection)
453  preview_reduction, int, m_preview_reduction, configSource, iniSection)
454 
455  // OpenCV options:
456  m_cv_camera_type = configSource.read_string_first_word(
457  iniSection, "cv_camera_type", m_cv_camera_type);
458  m_cv_camera_index =
459  configSource.read_int(iniSection, "cv_camera_index", m_cv_camera_index);
460 
461  m_cv_options.frame_width = configSource.read_int(
462  iniSection, "cv_frame_width", m_cv_options.frame_width);
463  m_cv_options.frame_height = configSource.read_int(
464  iniSection, "cv_frame_height", m_cv_options.frame_height);
465  m_cv_options.gain =
466  configSource.read_double(iniSection, "cv_gain", m_cv_options.gain);
467  m_cv_options.ieee1394_fps = configSource.read_double(
468  iniSection, "cv_fps", m_cv_options.ieee1394_fps);
469 
470  m_capture_grayscale =
471  configSource.read_bool(iniSection, "capture_grayscale", false);
472 
473  m_cv_options.ieee1394_grayscale = m_capture_grayscale;
474 
475  // dc1394 options:
477  dc1394_camera_guid, uint64_t, m_dc1394_camera_guid, configSource,
478  iniSection)
480  dc1394_camera_unit, int, m_dc1394_camera_unit, configSource, iniSection)
481 
483  dc1394_frame_width, int, m_dc1394_options.frame_width, configSource,
484  iniSection)
486  dc1394_frame_height, int, m_dc1394_options.frame_height, configSource,
487  iniSection)
488 
490  dc1394_mode7, int, m_dc1394_options.mode7, configSource, iniSection)
491 
493  dc1394_shutter, int, m_dc1394_options.shutter, configSource, iniSection)
495  dc1394_gain, int, m_dc1394_options.gain, configSource, iniSection)
497  dc1394_gamma, int, m_dc1394_options.gamma, configSource, iniSection)
499  dc1394_brightness, int, m_dc1394_options.brightness, configSource,
500  iniSection)
502  dc1394_exposure, int, m_dc1394_options.exposure, configSource,
503  iniSection)
505  dc1394_sharpness, int, m_dc1394_options.sharpness, configSource,
506  iniSection)
508  dc1394_white_balance, int, m_dc1394_options.white_balance, configSource,
509  iniSection)
510 
512  dc1394_shutter_mode, int, m_dc1394_options.shutter_mode, configSource,
513  iniSection)
515  dc1394_gain_mode, int, m_dc1394_options.gain_mode, configSource,
516  iniSection)
518  dc1394_gamma_mode, int, m_dc1394_options.gamma_mode, configSource,
519  iniSection)
521  dc1394_brightness_mode, int, m_dc1394_options.brightness_mode,
522  configSource, iniSection)
524  dc1394_exposure_mode, int, m_dc1394_options.exposure_mode, configSource,
525  iniSection)
527  dc1394_sharpness_mode, int, m_dc1394_options.sharpness_mode,
528  configSource, iniSection)
530  dc1394_white_balance_mode, int, m_dc1394_options.white_balance_mode,
531  configSource, iniSection)
532 
534  dc1394_trigger_power, int, m_dc1394_options.trigger_power, configSource,
535  iniSection)
537  dc1394_trigger_mode, int, m_dc1394_options.trigger_mode, configSource,
538  iniSection)
540  dc1394_trigger_source, int, m_dc1394_options.trigger_source,
541  configSource, iniSection)
543  dc1394_trigger_polarity, int, m_dc1394_options.trigger_polarity,
544  configSource, iniSection)
546  dc1394_ring_buffer_size, int, m_dc1394_options.ring_buffer_size,
547  configSource, iniSection)
548 
549  // Bumblebee_dc1394 options:
551  bumblebee_dc1394_camera_guid, uint64_t, m_bumblebee_dc1394_camera_guid,
552  configSource, iniSection)
554  bumblebee_dc1394_camera_unit, int, m_bumblebee_dc1394_camera_unit,
555  configSource, iniSection)
557  bumblebee_dc1394_framerate, double, m_bumblebee_dc1394_framerate,
558  configSource, iniSection)
559 
560  // SVS options:
561  m_svs_camera_index = configSource.read_int(
562  iniSection, "svs_camera_index", m_svs_camera_index);
563  m_svs_options.frame_width = configSource.read_int(
564  iniSection, "svs_frame_width", m_svs_options.frame_width);
565  m_svs_options.frame_height = configSource.read_int(
566  iniSection, "svs_frame_height", m_svs_options.frame_height);
567  m_svs_options.framerate = configSource.read_double(
568  iniSection, "svs_framerate", m_svs_options.framerate);
569  m_svs_options.m_NDisp =
570  configSource.read_int(iniSection, "svs_NDisp", m_svs_options.m_NDisp);
571  m_svs_options.m_Corrsize = configSource.read_int(
572  iniSection, "svs_Corrsize", m_svs_options.m_Corrsize);
573  m_svs_options.m_LR =
574  configSource.read_int(iniSection, "svs_LR", m_svs_options.m_LR);
575  m_svs_options.m_Thresh =
576  configSource.read_int(iniSection, "svs_Thresh", m_svs_options.m_Thresh);
577  m_svs_options.m_Unique =
578  configSource.read_int(iniSection, "svs_Unique", m_svs_options.m_Unique);
579  m_svs_options.m_Horopter = configSource.read_int(
580  iniSection, "svs_Horopter", m_svs_options.m_Horopter);
581  m_svs_options.m_SpeckleSize = configSource.read_int(
582  iniSection, "svs_SpeckleSize", m_svs_options.m_SpeckleSize);
583  m_svs_options.m_procesOnChip = configSource.read_bool(
584  iniSection, "svs_procesOnChip", m_svs_options.m_procesOnChip);
585  m_svs_options.m_calDisparity = configSource.read_bool(
586  iniSection, "svs_calDisparity", m_svs_options.m_calDisparity);
587 
588  // FFmpeg options:
589  m_ffmpeg_url = mrpt::system::trim(
590  configSource.read_string(iniSection, "ffmpeg_url", m_ffmpeg_url));
591 
592  // Rawlog options:
593  m_rawlog_file = mrpt::system::trim(
594  configSource.read_string(iniSection, "rawlog_file", m_rawlog_file));
595  m_rawlog_camera_sensor_label = mrpt::system::trim(configSource.read_string(
596  iniSection, "rawlog_camera_sensor_label",
597  m_rawlog_camera_sensor_label));
598 
599  // Image directory options:
600  m_img_dir_url = mrpt::system::trim(
601  configSource.read_string(iniSection, "image_dir_url", m_img_dir_url));
602  m_img_dir_left_format = mrpt::system::trim(configSource.read_string(
603  iniSection, "left_format", m_img_dir_left_format));
604  m_img_dir_right_format = mrpt::system::trim(
605  configSource.read_string(iniSection, "right_format", ""));
606  m_img_dir_start_index =
607  configSource.read_int(iniSection, "start_index", m_img_dir_start_index);
608  ;
609  m_img_dir_end_index =
610  configSource.read_int(iniSection, "end_index", m_img_dir_end_index);
611 
612  m_img_dir_is_stereo = !m_img_dir_right_format.empty();
613  m_img_dir_counter = m_img_dir_start_index;
614 
615  // DUO3D Camera options:
616  m_duo3d_options.loadOptionsFrom(configSource, "DUO3DOptions");
617 
618  // SwissRanger options:
619  m_sr_open_from_usb =
620  configSource.read_bool(iniSection, "sr_use_usb", m_sr_open_from_usb);
621  m_sr_ip_address =
622  configSource.read_string(iniSection, "sr_IP", m_sr_ip_address);
623 
624  m_sr_save_3d =
625  configSource.read_bool(iniSection, "sr_grab_3d", m_sr_save_3d);
626  m_sr_save_intensity_img = configSource.read_bool(
627  iniSection, "sr_grab_grayscale", m_sr_save_intensity_img);
628  m_sr_save_range_img = configSource.read_bool(
629  iniSection, "sr_grab_range", m_sr_save_range_img);
630  m_sr_save_confidence = configSource.read_bool(
631  iniSection, "sr_grab_confidence", m_sr_save_confidence);
632 
633  m_kinect_save_3d =
634  configSource.read_bool(iniSection, "kinect_grab_3d", m_kinect_save_3d);
635  m_kinect_save_intensity_img = configSource.read_bool(
636  iniSection, "kinect_grab_intensity", m_kinect_save_intensity_img);
637  m_kinect_save_range_img = configSource.read_bool(
638  iniSection, "kinect_grab_range", m_kinect_save_range_img);
639  m_kinect_video_rgb = configSource.read_bool(
640  iniSection, "kinect_video_rgb", m_kinect_video_rgb);
641 
642  // FlyCap:
643  m_flycap_options.loadOptionsFrom(configSource, iniSection, "flycap_");
644 
645  // FlyCap stereo
646  m_fcs_start_synch_capture = configSource.read_bool(
647  iniSection, "fcs_start_synch_capture", m_fcs_start_synch_capture);
648  m_flycap_stereo_options[0].loadOptionsFrom(
649  configSource, iniSection, "fcs_LEFT_");
650  m_flycap_stereo_options[1].loadOptionsFrom(
651  configSource, iniSection, "fcs_RIGHT_");
652 
653  // Special stuff: FPS
654  map<double, grabber_dc1394_framerate_t> map_fps;
656  map_fps[1.875] = FRAMERATE_1_875;
657  map_fps[3.75] = FRAMERATE_3_75;
658  map_fps[7.5] = FRAMERATE_7_5;
659  map_fps[15] = FRAMERATE_15;
660  map_fps[30] = FRAMERATE_30;
661  map_fps[60] = FRAMERATE_60;
662  map_fps[120] = FRAMERATE_120;
663  map_fps[240] = FRAMERATE_240;
664 
665  // ... for dc1394
666  double the_fps =
667  configSource.read_double(iniSection, "dc1394_framerate", 15.0);
668  it_fps = map_fps.find(the_fps);
669  if (it_fps == map_fps.end())
671  "ERROR: DC1394 framerate seems to be not a valid number: %f",
672  the_fps);
673 
674  m_dc1394_options.framerate = it_fps->second;
675 
676  // Special stuff: color encoding:
677  map<string, grabber_dc1394_color_coding_t> map_color;
679 #define ADD_COLOR_MAP(c) map_color[#c] = c;
686 
687  string the_color_coding =
689  iniSection, "dc1394_color_coding", "COLOR_CODING_YUV422"));
690  it_color = map_color.find(the_color_coding);
691  if (it_color == map_color.end())
693  "ERROR: Color coding seems not to be valid : '%s'",
694  the_color_coding.c_str());
695  m_dc1394_options.color_coding = it_color->second;
696 
697  m_external_images_format = mrpt::system::trim(configSource.read_string(
698  iniSection, "external_images_format", m_external_images_format));
699  m_external_images_jpeg_quality = configSource.read_int(
700  iniSection, "external_images_jpeg_quality",
701  m_external_images_jpeg_quality);
702  m_external_images_own_thread = configSource.read_bool(
703  iniSection, "external_images_own_thread", m_external_images_own_thread);
704  m_external_image_saver_count = configSource.read_int(
705  iniSection, "external_images_own_thread_count",
706  m_external_image_saver_count);
707 
708  // Sensor pose:
709  m_sensorPose.setFromValues(
710  configSource.read_float(iniSection, "pose_x", 0),
711  configSource.read_float(iniSection, "pose_y", 0),
712  configSource.read_float(iniSection, "pose_z", 0),
713  DEG2RAD(configSource.read_float(iniSection, "pose_yaw", 0)),
714  DEG2RAD(configSource.read_float(iniSection, "pose_pitch", 0)),
715  DEG2RAD(configSource.read_float(iniSection, "pose_roll", 0)));
716 }
717 
718 /* -----------------------------------------------------
719  Destructor
720  ----------------------------------------------------- */
722 {
723  close();
724 
725  m_preview_win1.reset();
726  m_preview_win2.reset();
727 }
728 /* -----------------------------------------------------
729  getNextFrame
730 ----------------------------------------------------- */
732 {
733  vector<CSerializable::Ptr> out_obs;
734  getNextFrame(out_obs);
735  return std::dynamic_pointer_cast<CObservation>(out_obs[0]);
736 }
737 
738 /* -----------------------------------------------------
739  getNextFrame
740 ----------------------------------------------------- */
741 void CCameraSensor::getNextFrame(vector<CSerializable::Ptr>& out_obs)
742 {
746  obs3D; // 3D range image, also with an intensity channel
747  CObservationIMU::Ptr obsIMU; // IMU observation grabbed by DUO3D cameras
748 
749  bool capture_ok = false;
750 
751  if (m_cap_cv)
752  {
753  obs = mrpt::make_aligned_shared<CObservationImage>();
754  if (!m_cap_cv->getObservation(*obs))
755  { // Error
756  m_state = CGenericSensor::ssError;
757  THROW_EXCEPTION("Error grabbing image");
758  }
759  else
760  capture_ok = true;
761  }
762  else if (m_cap_dc1394)
763  {
764  obs = mrpt::make_aligned_shared<CObservationImage>();
765  if (!m_cap_dc1394->getObservation(*obs))
766  { // Error
767  m_state = CGenericSensor::ssError;
768  THROW_EXCEPTION("Error grabbing image");
769  }
770  else
771  capture_ok = true;
772  }
773  else if (m_cap_swissranger)
774  {
775  obs3D = mrpt::make_aligned_shared<CObservation3DRangeScan>();
776 
777  bool there_is_obs, hardware_error;
778  m_cap_swissranger->getNextObservation(
779  *obs3D, there_is_obs, hardware_error);
780 
781  if (!there_is_obs || hardware_error)
782  { // Error
783  m_state = CGenericSensor::ssError;
784  THROW_EXCEPTION("Error grabbing image from SwissRanger camera.");
785  }
786  else
787  capture_ok = true;
788  }
789  else if (m_cap_kinect)
790  {
791  obs3D = mrpt::make_aligned_shared<CObservation3DRangeScan>();
792 
793  // Specially at start-up, there may be a delay grabbing so a few calls
794  // return false: add a timeout.
796  double max_timeout = 3.0; // seconds
797 
798  // If we have an "MRPT_CCAMERA_KINECT_TIMEOUT_MS" environment variable,
799  // use that timeout instead:
800  const char* envVal = getenv("MRPT_CCAMERA_KINECT_TIMEOUT_MS");
801  if (envVal) max_timeout = atoi(envVal) * 0.001;
802 
803  bool there_is_obs, hardware_error;
804  do
805  {
806  m_cap_kinect->getNextObservation(
807  *obs3D, there_is_obs, hardware_error);
808  if (!there_is_obs) std::this_thread::sleep_for(1ms);
809  } while (!there_is_obs && mrpt::system::timeDifference(
810  t0, mrpt::system::now()) < max_timeout);
811 
812  if (!there_is_obs || hardware_error)
813  { // Error
814  m_state = CGenericSensor::ssError;
815  THROW_EXCEPTION("Error grabbing image from Kinect camera.");
816  }
817  else
818  capture_ok = true;
819  }
820  else if (m_cap_openni2)
821  {
822  obs3D = mrpt::make_aligned_shared<CObservation3DRangeScan>();
823  // Specially at start-up, there may be a delay grabbing so a few calls
824  // return false: add a timeout.
826  double max_timeout = 3.0; // seconds
827  bool there_is_obs, hardware_error;
828  do
829  {
830  m_cap_openni2->getNextObservation(
831  *obs3D, there_is_obs, hardware_error);
832  if (!there_is_obs) std::this_thread::sleep_for(1ms);
833  } while (!there_is_obs && mrpt::system::timeDifference(
834  t0, mrpt::system::now()) < max_timeout);
835 
836  if (!there_is_obs || hardware_error)
837  { // Error
838  m_state = CGenericSensor::ssError;
839  THROW_EXCEPTION("Error grabbing image from OpenNI2 camera.");
840  }
841  else
842  capture_ok = true;
843  }
844  else if (m_cap_bumblebee_dc1394)
845  {
846  stObs = mrpt::make_aligned_shared<CObservationStereoImages>();
847  if (!m_cap_bumblebee_dc1394->getStereoObservation(*stObs))
848  {
849  m_state = CGenericSensor::ssError;
850  THROW_EXCEPTION("Error grabbing stereo images");
851  }
852  else
853  {
854  capture_ok = true;
855  }
856  }
857  else if (m_cap_svs)
858  {
859  stObs = mrpt::make_aligned_shared<CObservationStereoImages>();
860 
861  if (!m_cap_svs->getStereoObservation(*stObs))
862  {
863  // Error
864  m_state = CGenericSensor::ssError;
865  THROW_EXCEPTION("Error grabbing disparity images");
866  }
867  else
868  capture_ok = true;
869  }
870  else if (m_cap_ffmpeg)
871  {
872  obs = mrpt::make_aligned_shared<CObservationImage>();
873 
874  if (!m_cap_ffmpeg->retrieveFrame(obs->image))
875  { // Error
876  m_state = CGenericSensor::ssError;
877  THROW_EXCEPTION("Error grabbing image");
878  }
879  else
880  capture_ok = true;
881  }
882  else if (m_cap_image_dir)
883  {
884  if (m_img_dir_counter > m_img_dir_end_index)
885  {
886  m_state = CGenericSensor::ssError;
887  THROW_EXCEPTION("Reached end index.");
888  }
889 
890  std::string auxL = format(
891  "%s/%s", m_img_dir_url.c_str(), m_img_dir_left_format.c_str());
892  if (m_img_dir_is_stereo)
893  {
894  stObs = mrpt::make_aligned_shared<CObservationStereoImages>();
895  if (!stObs->imageLeft.loadFromFile(
896  format(auxL.c_str(), m_img_dir_counter)))
897  {
898  m_state = CGenericSensor::ssError;
899  THROW_EXCEPTION("Error reading images from directory");
900  }
901  std::string auxR = format(
902  "%s/%s", m_img_dir_url.c_str(), m_img_dir_right_format.c_str());
903  if (!stObs->imageRight.loadFromFile(
904  format(auxR.c_str(), m_img_dir_counter++)))
905  {
906  m_state = CGenericSensor::ssError;
907  THROW_EXCEPTION("Error reading images from directory");
908  }
909  else
910  capture_ok = true;
911  }
912  else
913  {
914  // use only left image prefix
915  obs = mrpt::make_aligned_shared<CObservationImage>();
916  if (!obs->image.loadFromFile(
917  format(auxL.c_str(), m_img_dir_counter++)))
918  {
919  m_state = CGenericSensor::ssError;
920  THROW_EXCEPTION("Error reading images from directory");
921  }
922  else
923  capture_ok = true;
924  }
925  }
926  else if (m_cap_rawlog)
927  {
928  // Read in a loop until we found at least one image:
929  // Assign to: obs && stObs
930  CSerializable::Ptr newObs;
931  while (!obs && !stObs && !obs3D)
932  {
933  archiveFrom(*m_cap_rawlog) >> newObs;
934  if (IS_DERIVED(newObs, CObservation))
935  {
937  std::dynamic_pointer_cast<CObservation>(newObs);
938  if (!m_rawlog_camera_sensor_label.empty() &&
939  m_rawlog_camera_sensor_label != o->sensorLabel)
940  continue;
941 
942  if (IS_CLASS(o, CObservationImage))
943  obs = std::dynamic_pointer_cast<CObservationImage>(o);
944  else if (IS_CLASS(o, CObservationStereoImages))
945  stObs =
946  std::dynamic_pointer_cast<CObservationStereoImages>(o);
947  else if (IS_CLASS(o, CObservation3DRangeScan))
948  obs3D =
949  std::dynamic_pointer_cast<CObservation3DRangeScan>(o);
950  }
951  else if (IS_CLASS(newObs, CSensoryFrame))
952  {
953  CSensoryFrame::Ptr sf =
954  std::dynamic_pointer_cast<CSensoryFrame>(newObs);
955 
956  for (CSensoryFrame::iterator i = sf->begin(); i != sf->end();
957  ++i)
958  {
959  CObservation::Ptr& o = *i;
960 
961  if (!m_rawlog_camera_sensor_label.empty() &&
962  m_rawlog_camera_sensor_label != o->sensorLabel)
963  continue;
964 
965  if (IS_CLASS(o, CObservationImage))
966  {
967  obs = std::dynamic_pointer_cast<CObservationImage>(o);
968  break;
969  }
970  else if (IS_CLASS(o, CObservationStereoImages))
971  {
972  stObs =
973  std::dynamic_pointer_cast<CObservationStereoImages>(
974  o);
975  break;
976  }
977  else if (IS_CLASS(o, CObservation3DRangeScan))
978  {
979  obs3D =
980  std::dynamic_pointer_cast<CObservation3DRangeScan>(
981  o);
982  break;
983  }
984  }
985  }
986  if (obs || stObs || obs3D)
987  {
988  // We must convert externally stored images into "normal
989  // in-memory" images.
990  const std::string old_dir =
991  CImage::getImagesPathBase(); // Save current
992  CImage::setImagesPathBase(m_rawlog_detected_images_dir);
993 
994  if (obs && obs->image.isExternallyStored())
995  obs->image.loadFromFile(
996  obs->image.getExternalStorageFileAbsolutePath());
997 
998  if (obs3D && obs3D->hasIntensityImage &&
999  obs3D->intensityImage.isExternallyStored())
1000  obs3D->intensityImage.loadFromFile(
1001  obs3D->intensityImage
1002  .getExternalStorageFileAbsolutePath());
1003 
1004  if (stObs && stObs->imageLeft.isExternallyStored())
1005  stObs->imageLeft.loadFromFile(
1006  stObs->imageLeft.getExternalStorageFileAbsolutePath());
1007 
1008  if (stObs && stObs->hasImageRight &&
1009  stObs->imageRight.isExternallyStored())
1010  stObs->imageRight.loadFromFile(
1011  stObs->imageRight.getExternalStorageFileAbsolutePath());
1012 
1013  if (stObs && stObs->hasImageDisparity &&
1014  stObs->imageDisparity.isExternallyStored())
1015  stObs->imageDisparity.loadFromFile(
1016  stObs->imageDisparity
1017  .getExternalStorageFileAbsolutePath());
1018 
1019  CImage::setImagesPathBase(old_dir); // Restore
1020  }
1021  else
1022  continue; // Keep reading
1023  }
1024  capture_ok = true;
1025  }
1026  else if (m_cap_flycap)
1027  {
1028  bool ok;
1029  if (!m_cap_flycap->isStereo()) // Mono image
1030  {
1031  obs = mrpt::make_aligned_shared<CObservationImage>();
1032  ok = m_cap_flycap->getObservation(*obs);
1033  }
1034  else // Stereo camera connected
1035  {
1036  stObs = mrpt::make_aligned_shared<CObservationStereoImages>();
1037  ok = m_cap_flycap->getObservation(*stObs);
1038  }
1039 
1040  if (!ok)
1041  { // Error
1042  m_state = CGenericSensor::ssError;
1043  THROW_EXCEPTION("Error grabbing image");
1044  }
1045  else
1046  capture_ok = true;
1047  }
1048  else if (m_cap_flycap_stereo_l && m_cap_flycap_stereo_r)
1049  {
1050  stObs = mrpt::make_aligned_shared<CObservationStereoImages>();
1051 
1052  CObservationImage obsL, obsR;
1053 
1054  bool ok1, ok2 = false;
1055 
1056  ok1 = m_cap_flycap_stereo_r->getObservation(obsL);
1057  if (ok1) ok2 = m_cap_flycap_stereo_l->getObservation(obsR);
1058 
1059  if (!ok1 || !ok2)
1060  {
1061  // Error
1062  m_state = CGenericSensor::ssError;
1063  THROW_EXCEPTION("Error grabbing disparity images");
1064  }
1065  else
1066  {
1067  // Joint the two images as one stereo:
1068  const double At =
1069  mrpt::system::timeDifference(obsL.timestamp, obsR.timestamp);
1070  if (std::abs(At) > 0.1)
1071  {
1072  cout << "[CCamera, flycap_stereo] Warning: Too large delay "
1073  "between left & right images: "
1074  << At << " sec.\n";
1075  }
1076 
1077  // It seems that the timestamp is not always filled in from FlyCap
1078  // driver?
1079  stObs->timestamp = (obsL.timestamp != INVALID_TIMESTAMP)
1080  ? obsL.timestamp
1081  : mrpt::system::now();
1082  stObs->imageLeft.copyFastFrom(obsL.image);
1083  stObs->imageRight.copyFastFrom(obsR.image);
1084  capture_ok = true;
1085  }
1086  }
1087  else if (m_cap_duo3d)
1088  {
1089  stObs = mrpt::make_aligned_shared<CObservationStereoImages>();
1090  obsIMU = mrpt::make_aligned_shared<CObservationIMU>();
1091 
1092  bool thereIsIMG, thereIsIMU;
1093  m_cap_duo3d->getObservations(*stObs, *obsIMU, thereIsIMG, thereIsIMU);
1094  if (!thereIsIMG)
1095  {
1096  m_state = CGenericSensor::ssError;
1097  THROW_EXCEPTION("Error getting observations from DUO3D camera.");
1098  }
1099  else if (m_cap_duo3d->captureIMUIsSet() && !thereIsIMU)
1100  {
1101  cout << "[CCamera, duo3d] Warning: There are no IMU data from the "
1102  "device. Only images are being grabbed.";
1103  }
1104  capture_ok = true;
1105  }
1106  else
1107  {
1109  "There is no initialized camera driver: has 'initialize()' been "
1110  "called?")
1111  }
1112 
1113  ASSERT_(capture_ok);
1114 
1115  // Are we supposed to do a decimation??
1116  m_camera_grab_decimator_counter++;
1117  if (m_camera_grab_decimator_counter < m_camera_grab_decimator)
1118  {
1119  // Done here:
1120  out_obs.push_back(CObservation::Ptr());
1121  return;
1122  }
1123  // Continue as normal:
1124  m_camera_grab_decimator_counter = 0;
1125 
1126  ASSERT_(obs || stObs || obs3D || obsIMU);
1127  // If we grabbed an image: prepare it and add it to the internal queue:
1128  if (obs)
1129  {
1130  obs->sensorLabel = m_sensorLabel;
1131  obs->setSensorPose(m_sensorPose);
1132  }
1133  else if (stObs)
1134  {
1135  stObs->sensorLabel = (m_cap_duo3d && m_cap_duo3d->captureIMUIsSet())
1136  ? m_sensorLabel + "_IMG"
1137  : m_sensorLabel;
1138  stObs->setSensorPose(m_sensorPose);
1139  }
1140  else if (obs3D)
1141  {
1142  obs3D->sensorLabel = m_sensorLabel;
1143  obs3D->setSensorPose(m_sensorPose);
1144  }
1145  if (obsIMU)
1146  {
1147  obsIMU->sensorLabel = m_sensorLabel + "_IMU";
1148  obsIMU->setSensorPose(m_sensorPose);
1149  }
1150 
1151  // Convert to grayscale if the user wants so and the driver did ignored us:
1152  if (m_capture_grayscale)
1153  {
1154  if (obs)
1155  {
1156  if (obs->image.isColor()) obs->image.grayscaleInPlace();
1157  }
1158  else if (stObs)
1159  {
1160  if (stObs->imageLeft.isColor()) stObs->imageLeft.grayscaleInPlace();
1161  if (stObs->hasImageRight && stObs->imageRight.isColor())
1162  stObs->imageRight.grayscaleInPlace();
1163  if (stObs->hasImageDisparity && stObs->imageDisparity.isColor())
1164  stObs->imageDisparity
1165  .grayscaleInPlace(); // Shouldn't happen, but...
1166  }
1167  else if (obs3D)
1168  {
1169  if (obs3D->hasIntensityImage && obs3D->intensityImage.isColor())
1170  obs3D->intensityImage.grayscaleInPlace();
1171  }
1172  }
1173  // External storage?
1174  bool delayed_insertion_in_obs_queue =
1175  false; // If true, we'll return nothing, but the observation will be
1176  // inserted from the thread.
1177 
1178  if (!m_path_for_external_images.empty())
1179  {
1180  if (stObs) // If we have grabbed an stereo observation ...
1181  { // Stereo obs -------
1182  if (m_external_images_own_thread)
1183  {
1184  m_csToSaveList.lock();
1185 
1186  // Select the "m_toSaveList" with the shortest pending queue:
1187  size_t idx_min = 0;
1188  for (size_t i = 0; i < m_toSaveList.size(); ++i)
1189  if (m_toSaveList[i].size() < m_toSaveList[idx_min].size())
1190  idx_min = i;
1191  // Insert:
1192  m_toSaveList[idx_min].insert(
1193  TListObsPair(stObs->timestamp, stObs));
1194 
1195  m_csToSaveList.unlock();
1196 
1197  delayed_insertion_in_obs_queue = true;
1198  }
1199  else
1200  {
1201  const string filNameL =
1202  fileNameStripInvalidChars(trim(m_sensorLabel)) +
1203  format(
1204  "_L_%f.%s", (double)timestampTotime_t(stObs->timestamp),
1205  m_external_images_format.c_str());
1206  const string filNameR =
1207  fileNameStripInvalidChars(trim(m_sensorLabel)) +
1208  format(
1209  "_R_%f.%s", (double)timestampTotime_t(stObs->timestamp),
1210  m_external_images_format.c_str());
1211  const string filNameD =
1212  fileNameStripInvalidChars(trim(m_sensorLabel)) +
1213  format(
1214  "_D_%f.%s", (double)timestampTotime_t(stObs->timestamp),
1215  m_external_images_format.c_str());
1216  // cout << "[CCameraSensor] Saving " << filName << endl;
1217  stObs->imageLeft.saveToFile(
1218  m_path_for_external_images + string("/") + filNameL,
1219  m_external_images_jpeg_quality);
1220  stObs->imageLeft.setExternalStorage(filNameL);
1221 
1222  if (stObs->hasImageRight)
1223  {
1224  stObs->imageRight.saveToFile(
1225  m_path_for_external_images + string("/") + filNameR,
1226  m_external_images_jpeg_quality);
1227  stObs->imageRight.setExternalStorage(filNameR);
1228  }
1229  if (stObs->hasImageDisparity)
1230  {
1231  stObs->imageDisparity.saveToFile(
1232  m_path_for_external_images + string("/") + filNameD,
1233  m_external_images_jpeg_quality);
1234  stObs->imageDisparity.setExternalStorage(filNameD);
1235  }
1236  }
1237  }
1238  else if (obs)
1239  { // Monocular image obs -------
1240  if (m_external_images_own_thread)
1241  {
1242  m_csToSaveList.lock();
1243 
1244  // Select the "m_toSaveList" with the shortest pending queue:
1245  size_t idx_min = 0;
1246  for (size_t i = 0; i < m_toSaveList.size(); ++i)
1247  if (m_toSaveList[i].size() < m_toSaveList[idx_min].size())
1248  idx_min = i;
1249 
1250  // Insert:
1251  m_toSaveList[idx_min].insert(TListObsPair(obs->timestamp, obs));
1252 
1253  m_csToSaveList.unlock();
1254  delayed_insertion_in_obs_queue = true;
1255  }
1256  else
1257  {
1258  string filName =
1259  fileNameStripInvalidChars(trim(m_sensorLabel)) +
1260  format(
1261  "_%f.%s", (double)timestampTotime_t(obs->timestamp),
1262  m_external_images_format.c_str());
1263  // cout << "[CCameraSensor] Saving " << filName << endl;
1264  obs->image.saveToFile(
1265  m_path_for_external_images + string("/") + filName,
1266  m_external_images_jpeg_quality);
1267  obs->image.setExternalStorage(filName);
1268  }
1269  } // end else
1270  }
1271 
1272  // Show preview??
1273  if (m_preview_decimation > 0)
1274  { // Yes
1275  if (++m_preview_counter > m_preview_decimation)
1276  {
1277  m_preview_counter = 0;
1278 
1279  // Create window the first time:
1280  if (!m_preview_win1)
1281  {
1282  string caption = string("Preview of ") + m_sensorLabel;
1283  if (stObs) caption += "-LEFT";
1284  if (m_preview_decimation > 1)
1285  caption +=
1286  format(" (decimation: %i)", m_preview_decimation);
1287  m_preview_win1 =
1288  mrpt::make_aligned_shared<mrpt::gui::CDisplayWindow>(
1289  caption);
1290  }
1291  if (stObs && !m_preview_win2)
1292  {
1293  string caption = string("Preview of ") + m_sensorLabel;
1294  if (stObs) caption += "-RIGHT";
1295  if (m_preview_decimation > 1)
1296  caption +=
1297  format(" (decimation: %i)", m_preview_decimation);
1298  m_preview_win2 =
1299  mrpt::make_aligned_shared<mrpt::gui::CDisplayWindow>(
1300  caption);
1301  }
1302  // Monocular image or Left from a stereo pair:
1303  if (m_preview_win1->isOpen())
1304  {
1305  CImage* img;
1306  if (stObs)
1307  img = &stObs->imageLeft;
1308  else if (obs)
1309  img = &obs->image;
1310  else
1311  img = &obs3D->intensityImage;
1312 
1313  // Apply image reduction?
1314  if (m_preview_reduction >= 2)
1315  {
1316  unsigned int w = img->getWidth();
1317  unsigned int h = img->getHeight();
1318  CImage auxImg;
1319  img->scaleImage(
1320  auxImg, w / m_preview_reduction,
1321  h / m_preview_reduction, IMG_INTERP_NN);
1322  m_preview_win1->showImage(auxImg);
1323  }
1324  else
1325  m_preview_win1->showImage(*img);
1326  }
1327 
1328  // Right from a stereo pair:
1329  if (m_preview_win2 && m_preview_win2->isOpen() && stObs &&
1330  stObs->hasImageRight)
1331  {
1332  // Apply image reduction?
1333  if (m_preview_reduction >= 2)
1334  {
1335  unsigned int w = stObs->imageRight.getWidth();
1336  unsigned int h = stObs->imageRight.getHeight();
1337  CImage auxImg;
1338  stObs->imageRight.scaleImage(
1339  auxImg, w / m_preview_reduction,
1340  h / m_preview_reduction, IMG_INTERP_NN);
1341  m_preview_win2->showImage(auxImg);
1342  }
1343  else
1344  m_preview_win2->showImage(stObs->imageRight);
1345  }
1346 
1347  // Disparity from a stereo pair:
1348  if (m_preview_win2 && m_preview_win2->isOpen() && stObs &&
1349  stObs->hasImageDisparity)
1350  {
1351  // Apply image reduction?
1352  if (m_preview_reduction >= 2)
1353  {
1354  unsigned int w = stObs->imageDisparity.getWidth();
1355  unsigned int h = stObs->imageDisparity.getHeight();
1356  CImage auxImg;
1357  stObs->imageDisparity.scaleImage(
1358  auxImg, w / m_preview_reduction,
1359  h / m_preview_reduction, IMG_INTERP_NN);
1360  m_preview_win2->showImage(auxImg);
1361  }
1362  else
1363  m_preview_win2->showImage(stObs->imageDisparity);
1364  }
1365  }
1366  } // end show preview
1367 
1368  if (delayed_insertion_in_obs_queue)
1369  {
1370  if (m_cap_duo3d && m_cap_duo3d->captureIMUIsSet() && obsIMU)
1371  out_obs.push_back(CObservation::Ptr(obsIMU));
1372  }
1373  else
1374  {
1375  if (stObs) out_obs.push_back(CObservation::Ptr(stObs));
1376  if (obs) out_obs.push_back(CObservation::Ptr(obs));
1377  if (obs3D) out_obs.push_back(CObservation::Ptr(obs3D));
1378  }
1379  return;
1380 }
1381 
1382 /* -----------------------------------------------------
1383  doProcess
1384 ----------------------------------------------------- */
1386 {
1387  vector<CSerializable::Ptr> out_obs;
1388  getNextFrame(out_obs);
1389  appendObservations(out_obs);
1390 }
1391 
1392 /* -----------------------------------------------------
1393  setSoftwareTriggerLevel
1394 ----------------------------------------------------- */
1396 {
1397  if (m_cap_dc1394)
1398  {
1399  if (!m_cap_dc1394->setSoftwareTriggerLevel(level))
1400  { // Error
1401  m_state = CGenericSensor::ssError;
1402  THROW_EXCEPTION("Error setting Trigger level by software");
1403  }
1404  }
1405  else
1406  {
1408  "Software trigger is not implemented for this camera type")
1409  }
1410 }
1411 
1412 /* -----------------------------------------------------
1413  setPathForExternalImages
1414 ----------------------------------------------------- */
1416 {
1417  if (!mrpt::system::createDirectory(directory))
1418  {
1420  "Error: Cannot create the directory for externally saved images: "
1421  "%s",
1422  directory.c_str())
1423  }
1424  m_path_for_external_images = directory;
1425 }
1426 
1427 /* ------------------------------------------------------------------------
1428  prepareVideoSourceFromUserSelection
1429  ------------------------------------------------------------------------ */
1431 {
1432 #if MRPT_HAS_WXWIDGETS
1433  // Create the main wxThread, if it doesn't exist yet:
1435  {
1436  std::cerr << "[mrpt::hwdrivers::prepareVideoSourceFromUserSelection] "
1437  "Error initiating Wx subsystem."
1438  << std::endl;
1439  return CCameraSensor::Ptr(); // Error!
1440  }
1441 
1442  std::promise<void> semDlg;
1443  std::promise<mrpt::gui::detail::TReturnAskUserOpenCamera> dlgSelection;
1444 
1445  // Create window:
1448  REQ->OPCODE = 700;
1449  REQ->sourceCameraSelectDialog = true;
1450  REQ->voidPtr = reinterpret_cast<void*>(&semDlg);
1451  REQ->voidPtr2 = reinterpret_cast<void*>(&dlgSelection);
1452  WxSubsystem::pushPendingWxRequest(REQ);
1453 
1454  // Wait for the window to realize and signal it's alive:
1455  if (!WxSubsystem::isConsoleApp())
1456  {
1457  std::this_thread::sleep_for(
1458  20ms); // Force at least 1-2 timer ticks for processing the event:
1459  wxApp::GetInstance()->Yield(true);
1460  }
1461 
1462  // wait for window construction:
1463  int maxTimeout =
1464 #ifdef _DEBUG
1465  30000;
1466 #else
1467  6000;
1468 #endif
1469  // If we have an "MRPT_WXSUBSYS_TIMEOUT_MS" environment variable, use that
1470  // timeout instead:
1471  const char* envVal = getenv("MRPT_WXSUBSYS_TIMEOUT_MS");
1472  if (envVal) maxTimeout = atoi(envVal);
1473 
1474  if (semDlg.get_future().wait_for(std::chrono::milliseconds(maxTimeout)) ==
1475  std::future_status::timeout)
1476  {
1477  cerr << "[prepareVideoSourceFromUserSelection] Timeout waiting window "
1478  "creation."
1479  << endl;
1480  return CCameraSensor::Ptr();
1481  }
1482 
1483  // wait for user selection:
1484  auto future = dlgSelection.get_future();
1485  future.wait();
1486 
1487  // If the user didn't accept the dialog, return now:
1488  if (!future.get().accepted_by_user) return CCameraSensor::Ptr();
1489 
1490  CCameraSensor::Ptr cam = mrpt::make_aligned_shared<CCameraSensor>();
1491  cam->loadConfig(future.get().selectedConfig, "CONFIG");
1492  cam->initialize(); // This will raise an exception if neccesary
1493 
1494  return cam;
1495 #else
1496  THROW_EXCEPTION("MRPT compiled without wxWidgets");
1497 #endif // MRPT_HAS_WXWIDGETS
1498 }
1499 
1500 /* ------------------------------------------------------------------------
1501  prepareVideoSourceFromPanel
1502  ------------------------------------------------------------------------ */
1504 {
1505 #if MRPT_HAS_WXWIDGETS
1506 
1507  try
1508  {
1509  CConfigFileMemory cfg;
1510  writeConfigFromVideoSourcePanel(_panel, "CONFIG", &cfg);
1511 
1512  // Try to open the camera:
1513  CCameraSensor::Ptr video = mrpt::make_aligned_shared<CCameraSensor>();
1514  video->loadConfig(cfg, "CONFIG");
1515 
1516  // This will raise an exception if neccesary
1517  video->initialize();
1518 
1519  return video;
1520  }
1521  catch (std::exception& e)
1522  {
1523  cerr << endl << e.what() << endl;
1524  wxMessageBox(_("Couldn't open video source"), _("Error"));
1525  return CCameraSensor::Ptr();
1526  }
1527 #else
1528  THROW_EXCEPTION("MRPT compiled without wxWidgets");
1529 #endif // MRPT_HAS_WXWIDGETS
1530 }
1531 
1532 /* ------------------------------------------------------------------------
1533  writeConfigFromVideoSourcePanel
1534  ------------------------------------------------------------------------ */
1536  void* _panel, const std::string& sect, mrpt::config::CConfigFileBase* cfg)
1537 {
1538  MRPT_START
1539 #if MRPT_HAS_WXWIDGETS
1540  ASSERT_(_panel);
1542  reinterpret_cast<mrpt::gui::CPanelCameraSelection*>(_panel);
1543  ASSERTMSG_(
1544  panel, "panel must be of type mrpt::gui::CPanelCameraSelection *");
1545  panel->writeConfigFromVideoSourcePanel(sect, cfg);
1546 
1547 #else
1548  THROW_EXCEPTION("MRPT compiled without wxWidgets");
1549 #endif // MRPT_HAS_WXWIDGETS
1550  MRPT_END
1551 }
1552 
1553 /* ------------------------------------------------------------------------
1554  readConfigIntoVideoSourcePanel
1555  ------------------------------------------------------------------------ */
1557  void* _panel, const std::string& sect,
1558  const mrpt::config::CConfigFileBase* cfg)
1559 {
1560  MRPT_START
1561 #if MRPT_HAS_WXWIDGETS
1562  ASSERT_(_panel);
1564  reinterpret_cast<mrpt::gui::CPanelCameraSelection*>(_panel);
1565  ASSERTMSG_(
1566  panel, "panel must be of type mrpt::gui::CPanelCameraSelection *");
1567 
1568  panel->readConfigIntoVideoSourcePanel(sect, cfg);
1569 
1570 #else
1571  THROW_EXCEPTION("MRPT compiled without wxWidgets");
1572 #endif // MRPT_HAS_WXWIDGETS
1573  MRPT_END
1574 }
1575 
1576 /* -----------------------------------------------------
1577  THREAD: Saver of external images
1578  ----------------------------------------------------- */
1579 void CCameraSensor::thread_save_images(unsigned int my_working_thread_index)
1580 {
1581  while (!m_threadImagesSaverShouldEnd)
1582  {
1583  TListObservations newObs;
1584 
1585  // is there any new image?
1586  m_csToSaveList.lock();
1587  m_toSaveList[my_working_thread_index].swap(newObs);
1588  m_csToSaveList.unlock();
1589 
1590  for (TListObservations::const_iterator i = newObs.begin();
1591  i != newObs.end(); ++i)
1592  {
1593  // Optional user-code hook:
1594  if (m_hook_pre_save)
1595  {
1596  if (IS_DERIVED(i->second, CObservation))
1597  {
1599  std::dynamic_pointer_cast<mrpt::obs::CObservation>(
1600  i->second);
1601  m_hook_pre_save(obs, m_hook_pre_save_param);
1602  }
1603  }
1604 
1605  if (IS_CLASS(i->second, CObservationImage))
1606  {
1608  std::dynamic_pointer_cast<CObservationImage>(i->second);
1609 
1610  string filName =
1611  fileNameStripInvalidChars(trim(m_sensorLabel)) +
1612  format(
1613  "_%f.%s", (double)timestampTotime_t(obs->timestamp),
1614  m_external_images_format.c_str());
1615 
1616  obs->image.saveToFile(
1617  m_path_for_external_images + string("/") + filName,
1618  m_external_images_jpeg_quality);
1619  obs->image.setExternalStorage(filName);
1620  }
1621  else if (IS_CLASS(i->second, CObservationStereoImages))
1622  {
1624  std::dynamic_pointer_cast<CObservationStereoImages>(
1625  i->second);
1626 
1627  const string filNameL =
1628  fileNameStripInvalidChars(trim(m_sensorLabel)) +
1629  format(
1630  "_L_%f.%s", (double)timestampTotime_t(stObs->timestamp),
1631  m_external_images_format.c_str());
1632  const string filNameR =
1633  fileNameStripInvalidChars(trim(m_sensorLabel)) +
1634  format(
1635  "_R_%f.%s", (double)timestampTotime_t(stObs->timestamp),
1636  m_external_images_format.c_str());
1637  const string filNameD =
1638  fileNameStripInvalidChars(trim(m_sensorLabel)) +
1639  format(
1640  "_D_%f.%s", (double)timestampTotime_t(stObs->timestamp),
1641  m_external_images_format.c_str());
1642 
1643  stObs->imageLeft.saveToFile(
1644  m_path_for_external_images + string("/") + filNameL,
1645  m_external_images_jpeg_quality);
1646  stObs->imageLeft.setExternalStorage(filNameL);
1647 
1648  if (stObs->hasImageRight)
1649  {
1650  stObs->imageRight.saveToFile(
1651  m_path_for_external_images + string("/") + filNameR,
1652  m_external_images_jpeg_quality);
1653  stObs->imageRight.setExternalStorage(filNameR);
1654  }
1655  if (stObs->hasImageDisparity)
1656  {
1657  stObs->imageDisparity.saveToFile(
1658  m_path_for_external_images + string("/") + filNameD,
1659  m_external_images_jpeg_quality);
1660  stObs->imageDisparity.setExternalStorage(filNameD);
1661  }
1662  }
1663 
1664  // Append now:
1665  appendObservation(i->second);
1666  }
1667 
1668  std::this_thread::sleep_for(2ms);
1669  }
1670 }
mrpt::io::CFileGZInputStream CFileGZInputStream
void * voidPtr
Parameters, depending on OPCODE.
Definition: WxSubsystem.h:227
This class implements a config file-like interface over a memory-stored string list.
Scalar * iterator
Definition: eigen_plugins.h:26
#define ADD_COLOR_MAP(c)
Declares a class derived from "CObservation" that encapsules an image from a camera, whose relative pose to robot is also stored.
A class for grabing stereo images from a STOC camera of Videre Design NOTE:
bool createDirectory(const std::string &dirName)
Creates a directory.
Definition: filesystem.cpp:158
std::deque< CObservation::Ptr >::iterator iterator
You can use CSensoryFrame::begin to get a iterator to the first element.
#define MRPT_START
Definition: exceptions.h:262
TCameraType
These capture types are like their OpenCV equivalents.
std::string read_string(const std::string &section, const std::string &name, const std::string &defaultValue, bool failIfNotFound=false) const
The data structure for each inter-thread request:
Definition: WxSubsystem.h:190
static ENUMTYPE name2value(const std::string &name)
Gives the numerical name for a given enum text name.
Definition: TEnumType.h:100
This "software driver" implements the communication protocol for interfacing a DUO3D Stereo Camera...
Definition: CDUO3DCamera.h:154
CCameraSensor::Ptr prepareVideoSourceFromUserSelection()
Show to the user a list of possible camera drivers and creates and open the selected camera...
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:41
A wrapper for Point Gray Research (PGR) FlyCapture2 API for capturing images from Firewire...
void doProcess()
This method will be invoked at a minimum rate of "process_rate" (Hz)
std::pair< mrpt::system::TTimeStamp, mrpt::serialization::CSerializable::Ptr > TListObsPair
double DEG2RAD(const double x)
Degrees to radians.
A class for grabing "range images" from a MESA imaging SwissRanger 3D cameras (SR-2, SR-3000, SR-4k).
Declares a class derived from "CObservation" that encapsules a 3D range scan measurement, as from a time-of-flight range camera or any other RGBD sensor.
mrpt::system::TTimeStamp now()
A shortcut for system::getCurrentTime.
Definition: datetime.h:87
Contains classes for various device interfaces.
void readConfigIntoVideoSourcePanel(void *panel, const std::string &in_cfgfile_section_name, const mrpt::config::CConfigFileBase *in_cfgfile)
Parse the given section of the given configuration file and set accordingly the controls of the wxWid...
A generic class which process a video file or other kind of input stream (http, rtsp) and allows the ...
float read_float(const std::string &section, const std::string &name, float defaultValue, bool failIfNotFound=false) const
STL namespace.
std::string fileNameStripInvalidChars(const std::string &filename, const char replacement_to_invalid_chars='_')
Replace invalid filename chars by underscores (&#39;_&#39;) or any other user-given char. ...
Definition: filesystem.cpp:328
int OPCODE
Valid codes are: For CDisplayWindow:
Definition: WxSubsystem.h:297
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:4178
A class for grabing "range images", intensity images (either RGB or IR) and other information from an...
void writeConfigFromVideoSourcePanel(void *panel, const std::string &in_cfgfile_section_name, mrpt::config::CConfigFileBase *out_cfgfile)
Parse the user options in the wxWidgets "panel" and write the configuration into the given section of...
int read_int(const std::string &section, const std::string &name, int defaultValue, bool failIfNotFound=false) const
CArchiveStreamBase< STREAM > archiveFrom(STREAM &s)
Helper function to create a templatized wrapper CArchive object for a: MRPT&#39;s CStream, std::istream, std::ostream, std::stringstream
Definition: CArchive.h:555
void thread_save_images(unsigned int my_working_thread_index)
Thread to save images to files.
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:113
mrpt::Clock::time_point TTimeStamp
A system independent time type, it holds the the number of 100-nanosecond intervals since January 1...
Definition: datetime.h:40
#define IS_DERIVED(ptrObj, class_name)
Evaluates to true if a pointer to an object (derived from mrpt::rtti::CObject) is an instance of the ...
Definition: CObject.h:108
A class for grabing "range images", intensity images (either RGB or IR) and other information from an...
Definition: CKinect.h:266
This class allows loading and storing values and vectors of different types from a configuration text...
void close()
Close the camera (if open).
The central class for camera grabbers in MRPT, implementing the "generic sensor" interface.
std::string lowerCase(const std::string &str)
Returns an lower-case version of a string.
std::shared_ptr< CCameraSensor > Ptr
virtual void setPathForExternalImages(const std::string &directory)
Set the path where to save off-rawlog image files (this class DOES take into account this path)...
GLint GLvoid * img
Definition: glext.h:3763
Versatile class for consistent logging and management of output messages.
A class for grabing images from a IEEE1394 (Firewire) camera using the libdc1394-2 library...
Grabs from a "Bumblebee" or "Bumblebee2" stereo camera using raw access to the libdc1394 library...
Observation class for either a pair of left+right or left+disparity images from a stereo camera...
This namespace contains representation of robot actions and observations.
Declares a class for storing a "sensory frame", a set of "observations" taken by the robot approximat...
Definition: CSensoryFrame.h:52
void readConfigIntoVideoSourcePanel(const std::string &sect, const mrpt::config::CConfigFileBase *cfg) const
Definition: WxUtils.cpp:1044
bool sourceCameraSelectDialog
Only one of source* can be non-nullptr, indicating the class that generated the request.
Definition: WxSubsystem.h:219
static std::string & trim(std::string &s)
std::string read_string_first_word(const std::string &section, const std::string &name, const std::string &defaultValue, bool failIfNotFound=false) const
Reads a configuration parameter of type "string", and keeps only the first word (this can be used to ...
#define ASSERTMSG_(f, __ERROR_MSG)
Defines an assertion mechanism.
Definition: exceptions.h:101
double read_double(const std::string &section, const std::string &name, double defaultValue, bool failIfNotFound=false) const
void writeConfigFromVideoSourcePanel(const std::string &sect, mrpt::config::CConfigFileBase *cfg) const
Definition: WxUtils.cpp:877
GLsizei const GLchar ** string
Definition: glext.h:4101
#define IMPLEMENTS_GENERIC_SENSOR(class_name, NameSpace)
This must be inserted in all CGenericSensor classes implementation files:
void loadConfig_sensorSpecific(const mrpt::config::CConfigFileBase &configSource, const std::string &iniSection)
See the class documentation at the top for expected parameters.
static void startSyncCapture(int numCameras, const CImageGrabber_FlyCapture2 **cameras_array)
Starts a synchronous capture of several cameras, which must have been already opened.
unsigned __int64 uint64_t
Definition: rptypes.h:50
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void scaleImage(unsigned int width, unsigned int height, TInterpolationMethod interp=IMG_INTERP_CUBIC)
Scales this image to a new size, interpolating as needed.
Definition: CImage.cpp:2217
std::multimap< mrpt::system::TTimeStamp, mrpt::serialization::CSerializable::Ptr > TListObservations
virtual void initialize()
Tries to open the camera, after setting all the parameters with a call to loadConfig.
Declares a class that represents any robot&#39;s observation.
Definition: CObservation.h:43
bool read_bool(const std::string &section, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:16
#define IS_CLASS(ptrObj, class_name)
Evaluates to true if the given pointer to an object (derived from mrpt::rtti::CObject) is of the give...
Definition: CObject.h:102
std::string upperCase(const std::string &str)
Returns a upper-case version of a string.
#define MRPT_END
Definition: exceptions.h:266
mrpt::obs::CObservation::Ptr getNextFrame()
Retrieves the next frame from the video source, raising an exception on any error.
A class for grabing images from a "OpenCV"-compatible camera, or from an AVI video file...
GLint level
Definition: glext.h:3600
void setSoftwareTriggerLevel(bool level)
Set Software trigger level value (ON or OFF) for cameras with this function available.
A panel to select the camera input from all the formats supported by MRPT.
Definition: WxUtils.h:171
#define MRPT_LOAD_HERE_CONFIG_VAR( variableName, variableType, targetVariable, configFileObject, sectionNameStr)
std::string trim(const std::string &str)
Removes leading and trailing spaces.
GLenum GLsizei GLenum format
Definition: glext.h:3531
Classes for creating GUI windows for 2D and 3D visualization.
Definition: about_box.h:14
GLsizeiptr size
Definition: glext.h:3923
double timeDifference(const mrpt::system::TTimeStamp t_first, const mrpt::system::TTimeStamp t_later)
Returns the time difference from t1 to t2 (positive if t2 is posterior to t1), in seconds...
Definition: datetime.h:122
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
Definition: exceptions.h:43
const Scalar * const_iterator
Definition: eigen_plugins.h:27
#define INVALID_TIMESTAMP
Represents an invalid timestamp, where applicable.
Definition: datetime.h:43
static bool createOneInstanceMainThread()
Thread-safe method to create one single instance of the main wxWidgets thread: it will create the thr...
double timestampTotime_t(const mrpt::system::TTimeStamp t)
Transform from TTimeStamp to standard "time_t" (actually a double number, it can contain fractions of...
Definition: datetime.cpp:50
CCameraSensor::Ptr prepareVideoSourceFromPanel(void *panel)
Used only from MRPT apps: Use with caution since "panel" MUST be a "mrpt::gui::CPanelCameraSelection ...
virtual ~CCameraSensor()
Destructor.
A class for storing images as grayscale or RGB bitmaps.
Definition: img/CImage.h:130



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 7d5e6d718 Fri Aug 24 01:51:28 2018 +0200 at lun nov 2 08:35:50 CET 2020