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 =
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 }
#define ADD_COLOR_MAP(c)
#define IMPLEMENTS_GENERIC_SENSOR(class_name, NameSpace)
This must be inserted in all CGenericSensor classes implementation files:
static std::string & trim(std::string &s)
#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
#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
This class allows loading and storing values and vectors of different types from a configuration text...
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 ...
bool read_bool(const std::string &section, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
double read_double(const std::string &section, const std::string &name, double defaultValue, bool failIfNotFound=false) const
std::string read_string(const std::string &section, const std::string &name, const std::string &defaultValue, bool failIfNotFound=false) const
int read_int(const std::string &section, const std::string &name, int defaultValue, bool failIfNotFound=false) const
float read_float(const std::string &section, const std::string &name, float defaultValue, bool failIfNotFound=false) const
This class implements a config file-like interface over a memory-stored string list.
A panel to select the camera input from all the formats supported by MRPT.
Definition: WxUtils.h:172
void writeConfigFromVideoSourcePanel(const std::string &sect, mrpt::config::CConfigFileBase *cfg) const
Definition: WxUtils.cpp:877
void readConfigIntoVideoSourcePanel(const std::string &sect, const mrpt::config::CConfigFileBase *cfg) const
Definition: WxUtils.cpp:1044
static bool createOneInstanceMainThread()
Thread-safe method to create one single instance of the main wxWidgets thread: it will create the thr...
The central class for camera grabbers in MRPT, implementing the "generic sensor" interface.
virtual void initialize()
Tries to open the camera, after setting all the parameters with a call to loadConfig.
void loadConfig_sensorSpecific(const mrpt::config::CConfigFileBase &configSource, const std::string &iniSection)
See the class documentation at the top for expected parameters.
void close()
Close the camera (if open).
mrpt::obs::CObservation::Ptr getNextFrame()
Retrieves the next frame from the video source, raising an exception on any error.
std::shared_ptr< CCameraSensor > Ptr
void thread_save_images(unsigned int my_working_thread_index)
Thread to save images to files.
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).
virtual ~CCameraSensor()
Destructor.
void doProcess()
This method will be invoked at a minimum rate of "process_rate" (Hz)
void setSoftwareTriggerLevel(bool level)
Set Software trigger level value (ON or OFF) for cameras with this function available.
This "software driver" implements the communication protocol for interfacing a DUO3D Stereo Camera.
Definition: CDUO3DCamera.h:155
A generic class which process a video file or other kind of input stream (http, rtsp) and allows the ...
std::multimap< mrpt::system::TTimeStamp, mrpt::serialization::CSerializable::Ptr > TListObservations
std::pair< mrpt::system::TTimeStamp, mrpt::serialization::CSerializable::Ptr > TListObsPair
A wrapper for Point Gray Research (PGR) FlyCapture2 API for capturing images from Firewire,...
static void startSyncCapture(int numCameras, const CImageGrabber_FlyCapture2 **cameras_array)
Starts a synchronous capture of several cameras, which must have been already opened.
A class for grabing images from a "OpenCV"-compatible camera, or from an AVI video file.
A class for grabing images from a IEEE1394 (Firewire) camera using the libdc1394-2 library.
A class for grabing "range images", intensity images (either RGB or IR) and other information from an...
Definition: CKinect.h:267
A class for grabing "range images", intensity images (either RGB or IR) and other information from an...
Grabs from a "Bumblebee" or "Bumblebee2" stereo camera using raw access to the libdc1394 library.
A class for grabing stereo images from a STOC camera of Videre Design NOTE:
A class for grabing "range images" from a MESA imaging SwissRanger 3D cameras (SR-2,...
A class for storing images as grayscale or RGB bitmaps.
Definition: img/CImage.h:131
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
Declares a class derived from "CObservation" that encapsules a 3D range scan measurement,...
std::shared_ptr< CObservation3DRangeScan > Ptr
Declares a class that represents any robot's observation.
Definition: CObservation.h:44
mrpt::system::TTimeStamp timestamp
The associated UTC time-stamp.
Definition: CObservation.h:60
std::shared_ptr< CObservation > Ptr
Definition: CObservation.h:45
std::shared_ptr< CObservationIMU > Ptr
Declares a class derived from "CObservation" that encapsules an image from a camera,...
mrpt::img::CImage image
The image captured by the camera, that is, the main piece of information of this observation.
std::shared_ptr< CObservationImage > Ptr
Observation class for either a pair of left+right or left+disparity images from a stereo camera.
std::shared_ptr< CObservationStereoImages > Ptr
Declares a class for storing a "sensory frame", a set of "observations" taken by the robot approximat...
Definition: CSensoryFrame.h:53
std::shared_ptr< CSensoryFrame > Ptr
Definition: CSensoryFrame.h:54
std::deque< CObservation::Ptr >::iterator iterator
You can use CSensoryFrame::begin to get a iterator to the first element.
std::shared_ptr< CSerializable > Ptr
Definition: CSerializable.h:35
Versatile class for consistent logging and management of output messages.
#define MRPT_LOAD_HERE_CONFIG_VAR( variableName, variableType, targetVariable, configFileObject, sectionNameStr)
Scalar * iterator
Definition: eigen_plugins.h:26
const Scalar * const_iterator
Definition: eigen_plugins.h:27
#define MRPT_START
Definition: exceptions.h:262
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:113
#define MRPT_END
Definition: exceptions.h:266
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:41
#define ASSERTMSG_(f, __ERROR_MSG)
Defines an assertion mechanism.
Definition: exceptions.h:101
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
Definition: exceptions.h:43
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:4178
GLint GLvoid * img
Definition: glext.h:3763
GLint level
Definition: glext.h:3600
GLsizeiptr size
Definition: glext.h:3923
GLenum GLsizei GLenum format
Definition: glext.h:3531
GLsizei const GLchar ** string
Definition: glext.h:4101
bool createDirectory(const std::string &dirName)
Creates a directory.
Definition: filesystem.cpp:158
std::string fileNameStripInvalidChars(const std::string &filename, const char replacement_to_invalid_chars='_')
Replace invalid filename chars by underscores ('_') or any other user-given char.
Definition: filesystem.cpp:328
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:16
std::string trim(const std::string &str)
Removes leading and trailing spaces.
std::string lowerCase(const std::string &str)
Returns an lower-case version of a string.
std::string upperCase(const std::string &str)
Returns a upper-case version of a string.
#define INVALID_TIMESTAMP
Represents an invalid timestamp, where applicable.
Definition: datetime.h:43
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
mrpt::system::TTimeStamp now()
A shortcut for system::getCurrentTime.
Definition: datetime.h:87
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
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
Classes for creating GUI windows for 2D and 3D visualization.
Definition: about_box.h:15
Contains classes for various device interfaces.
TCameraType
These capture types are like their OpenCV equivalents.
CCameraSensor::Ptr prepareVideoSourceFromPanel(void *panel)
Used only from MRPT apps: Use with caution since "panel" MUST be a "mrpt::gui::CPanelCameraSelection ...
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...
CCameraSensor::Ptr prepareVideoSourceFromUserSelection()
Show to the user a list of possible camera drivers and creates and open the selected camera.
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...
@ IMG_INTERP_NN
Definition: img/CImage.h:36
This namespace contains representation of robot actions and observations.
CArchiveStreamBase< STREAM > archiveFrom(STREAM &s)
Helper function to create a templatized wrapper CArchive object for a: MRPT's CStream,...
Definition: CArchive.h:555
mrpt::io::CFileGZInputStream CFileGZInputStream
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
double DEG2RAD(const double x)
Degrees to radians.
unsigned __int64 uint64_t
Definition: rptypes.h:50
The data structure for each inter-thread request:
Definition: WxSubsystem.h:191
bool sourceCameraSelectDialog
Only one of source* can be non-nullptr, indicating the class that generated the request.
Definition: WxSubsystem.h:219
int OPCODE
Valid codes are: For CDisplayWindow:
Definition: WxSubsystem.h:297
void * voidPtr
Parameters, depending on OPCODE.
Definition: WxSubsystem.h:227
static ENUMTYPE name2value(const std::string &name)
Gives the numerical name for a given enum text name.
Definition: TEnumType.h:100



Page generated by Doxygen 1.9.1 for MRPT 1.9.9 Git: 814d80880 Fri Aug 24 01:51:28 2018 +0200 at mar 26 may 2026 12:30:59 CEST