17 #include <mrpt/otherlibs/do_opencv_includes.h>
41 std::vector<std::shared_ptr<COpenNI2Generic::CDevice>>
vDevices;
46 bool setONI2StreamMode(
47 openni::VideoStream& stream,
int w,
int h,
int fps,
48 openni::PixelFormat
format);
49 std::string oni2DevInfoStr(
const openni::DeviceInfo& info,
int tab = 0);
50 bool cmpONI2Device(
const openni::DeviceInfo& i1,
const openni::DeviceInfo& i2);
51 #endif // MRPT_HAS_OPENNI2
68 m_rgb_format(openni::PIXEL_FORMAT_RGB888),
69 m_depth_format(openni::PIXEL_FORMAT_DEPTH_1_MM),
74 m_grab_3D_points(true)
76 const char* sVerbose = getenv(
"MRPT_HWDRIVERS_VERBOSE");
77 m_verbose = (sVerbose !=
nullptr) && atoi(sVerbose) != 0;
84 "After initialization:\n %s\n",
85 openni::OpenNI::getExtendedError()))
91 int width,
int height,
float fps,
bool open_streams_now)
96 m_rgb_format(openni::PIXEL_FORMAT_RGB888),
97 m_depth_format(openni::PIXEL_FORMAT_DEPTH_1_MM),
102 m_grab_3D_points(true)
104 const char* sVerbose = getenv(
"MRPT_HWDRIVERS_VERBOSE");
105 m_verbose = (sVerbose !=
nullptr) && atoi(sVerbose) != 0;
107 if (open_streams_now)
114 "After initialization:\n %s\n",
115 openni::OpenNI::getExtendedError()))
126 if (openni::OpenNI::initialize() != openni::STATUS_OK)
132 std::cerr <<
"[" << __FUNCTION__ <<
"]" << std::endl
133 <<
" Initialized OpenNI2." << std::endl;
140 #endif // MRPT_HAS_OPENNI2
157 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
168 std::cerr << message;
178 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
180 openni::Array<openni::DeviceInfo> oni2InfoArray;
181 openni::OpenNI::enumerateDevices(&oni2InfoArray);
183 const size_t numDevices = oni2InfoArray.getSize();
187 " Get device list. %d devices connected.\n", (
int)numDevices));
190 std::set<int> newDevices;
191 for (
unsigned i = 0; i < numDevices; i++)
193 const openni::DeviceInfo& info = oni2InfoArray[i];
195 showLog(oni2DevInfoStr(info, 3) +
"\n");
197 bool isExist =
false;
198 for (
unsigned int j = 0, j_end =
vDevices.size();
199 j < j_end && isExist ==
false; ++j)
201 if (cmpONI2Device(info,
vDevices[j]->getInfo()))
206 if (isExist ==
false)
208 newDevices.insert(i);
213 it_end = newDevices.end();
216 const openni::DeviceInfo& info = oni2InfoArray[*it];
223 if (device->getSerialNumber(sn))
226 mrpt::format(
"Device[%d]: serial number: `%u`\n", *it, sn));
233 showLog(
" No devices connected -> EXIT\n");
242 #endif // MRPT_HAS_OPENNI2
247 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
250 openni::OpenNI::shutdown();
253 #endif // MRPT_HAS_OPENNI2
259 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
264 return vDevices[sensor_id]->isOpen();
268 #endif // MRPT_HAS_OPENNI2
274 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
283 "Sensor index is higher than the number of connected devices.")
291 mrpt::format(
" The sensor [%d] is already opened\n", sensor_id));
296 "[COpenNI2Generic] DBG: [%s] about to call vDevices[%d]->open()\n",
297 __FUNCTION__, sensor_id);
303 showLog(
" open successfully.\n");
309 std::this_thread::sleep_for(1000ms);
313 #endif // MRPT_HAS_OPENNI2
317 const std::set<unsigned>& serial_required)
320 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
322 unsigned num_open_dev = 0;
323 for (
unsigned sensor_id = 0; sensor_id <
vDevices.size(); sensor_id++)
325 unsigned int serialNum;
326 if (
vDevices[sensor_id]->getSerialNumber(serialNum) ==
false)
333 "[COpenNI2Generic::openDevicesBySerialNum] checking device "
334 "with serial '%d'\n",
337 if (serial_required.find(serialNum) == serial_required.end())
351 "[COpenNI2Generic] DBG: [%s] about to call "
352 "vDevices[%d]->open(%d,%d,%d)\n",
362 "[COpenNI2Generic] DBG: [%s] now has %d devices open\n",
363 __FUNCTION__, num_open_dev);
369 #endif // MRPT_HAS_OPENNI2
373 const unsigned int SerialRequired)
375 std::set<unsigned> serial_required;
376 serial_required.insert(SerialRequired);
381 const unsigned int SerialRequired,
int& sensor_id)
const
384 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
385 for (
size_t i = 0, i_end =
vDevices.size(); i < i_end; ++i)
388 if (
vDevices[i]->getSerialNumber(sn) ==
false)
392 if (sn == SerialRequired)
403 #endif // MRPT_HAS_OPENNI2
409 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
418 "Sensor index is higher than the number of connected devices.")
424 #endif // MRPT_HAS_OPENNI2
438 bool& hardware_error,
unsigned sensor_id)
449 "Sensor index is higher than the number of connected devices.")
452 rgb_img, timestamp, there_is_obs, hardware_error) ==
false)
465 #endif // MRPT_HAS_OPENNI2
480 bool& hardware_error,
unsigned sensor_id)
491 "Sensor index is higher than the number of connected devices.")
494 depth_img, timestamp, there_is_obs, hardware_error) ==
false)
507 #endif // MRPT_HAS_OPENNI2
520 bool& hardware_error,
unsigned sensor_id)
531 "Sensor index is higher than the number of connected devices.")
534 out_obs, there_is_obs, hardware_error) ==
false)
546 #endif // MRPT_HAS_OPENNI2
553 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
554 if (
isOpen(sensor_id) ==
false)
563 #endif // MRPT_HAS_OPENNI2
570 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
571 if (
isOpen(sensor_id) ==
false)
580 #endif // MRPT_HAS_OPENNI2
593 bool setONI2StreamMode(
594 openni::VideoStream& stream,
int w,
int h,
int fps,
595 openni::PixelFormat
format)
600 const openni::Array<openni::VideoMode>& modes =
601 stream.getSensorInfo().getSupportedVideoModes();
602 for (
int i = 0, i_end = modes.getSize(); i < i_end; ++i)
608 if (modes[i].getResolutionX() !=
w)
612 if (modes[i].getResolutionY() != h)
616 if (modes[i].getFps() != fps)
620 if (modes[i].getPixelFormat() !=
format)
625 if (rc != openni::STATUS_OK)
634 std::string oni2DevInfoStr(
const openni::DeviceInfo& info,
int tab)
636 std::stringstream sst;
638 for (
int i = 0; i < tab; ++i)
642 sst << space <<
"name=" << info.getName() << std::endl;
643 sst << space <<
"uri=" << info.getUri() << std::endl;
644 sst << space <<
"vendor=" << info.getVendor() << std::endl;
645 sst << space <<
"product=" << info.getUsbProductId();
649 bool cmpONI2Device(
const openni::DeviceInfo& i1,
const openni::DeviceInfo& i2)
651 return (strcmp(i1.getUri(), i2.getUri()) == 0);
654 COpenNI2Generic::CDevice::CDevice(
655 const openni::DeviceInfo& info, openni::PixelFormat rgb,
656 openni::PixelFormat
depth,
bool verbose)
657 : m_info(info), m_mirror(true), m_verbose(verbose)
659 m_streams[COLOR_STREAM] =
660 CStream::create(m_device, openni::SENSOR_COLOR, rgb, m_log,
m_verbose);
661 m_streams[IR_STREAM] =
662 CStream::create(m_device, openni::SENSOR_IR, rgb, m_log,
m_verbose);
663 m_streams[DEPTH_STREAM] = CStream::create(
667 COpenNI2Generic::CDevice::~CDevice() {
close(); }
668 bool COpenNI2Generic::CDevice::synchMirrorMode()
672 for (
int i = 0; i < STREAM_TYPE_SIZE; ++i)
674 if (!m_streams[i])
continue;
678 mirror_support = m_streams[i]->isMirrorSupported();
680 catch (std::logic_error& e)
684 if (mirror_support ==
false)
686 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl;
687 m_log <<
" openni::STREAM_PROPERTY_MIRRORING is not supported on "
688 << m_streams[i]->getName() <<
"." << std::endl;
689 m_log <<
" We assume this is MS Kinect and taken images are "
690 "inverted to right and left."
699 for (
int i = 0; i < STREAM_TYPE_SIZE; ++i)
701 if (!m_streams[i])
continue;
702 if (m_streams[i]->isMirrorSupported() ==
false)
706 if (m_streams[i]->setMirror(m_mirror) ==
false)
714 bool COpenNI2Generic::CDevice::startStreams()
718 for (
int i = 0; i < STREAM_TYPE_SIZE; ++i)
720 if (!m_streams[i])
continue;
722 printf(
" [%s] calling m_streams[%d]->start()\n", __FUNCTION__, i);
723 if (m_streams[i]->
start() ==
false)
727 " [%s] m_streams[%d]->start() returned FALSE!\n",
736 " [%s] m_streams[%d]->start() returned TRUE\n", __FUNCTION__,
741 " [COpenNI2Generic::CDevice::startStreams()] %d streams were "
748 bool COpenNI2Generic::CDevice::isOpen()
const
750 return (m_streams[COLOR_STREAM] && m_streams[COLOR_STREAM]->isValid()) ||
751 (m_streams[DEPTH_STREAM] && m_streams[DEPTH_STREAM]->isValid());
754 void COpenNI2Generic::CDevice::close()
756 for (
int i = 0; i < STREAM_TYPE_SIZE; ++i)
758 if (!m_streams[i])
continue;
759 m_streams[i]->destroy();
764 bool COpenNI2Generic::CDevice::open(
int w,
int h,
int fps)
769 " [COpenNI2Generic::CDevice::open()] Called with w=%i h=%i "
775 if (rc != openni::STATUS_OK)
777 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl
778 <<
" Failed to open device " << getInfo().getUri() <<
" "
779 << openni::OpenNI::getExtendedError() << std::endl;
782 for (
int i = 0; i < STREAM_TYPE_SIZE; ++i)
784 if (!m_streams[i])
continue;
786 printf(
" [%s] calling m_streams[%d]->open()\n", __FUNCTION__, i);
788 if (m_streams[i]->
open(
w, h, fps) ==
false)
792 " [%s] m_streams[%d]->open() returned FALSE\n",
798 " [%s] m_streams[%d]->open() returned OK\n", __FUNCTION__, i);
801 if (synchMirrorMode() ==
false)
807 if (m_streams[DEPTH_STREAM])
810 m_streams[DEPTH_STREAM]->setCloseRange(CloseRange);
811 m_log <<
" Close range: " << (CloseRange ?
"On" :
"Off") << std::endl;
815 printf(
" DBG: checking if imageRegistrationMode is supported\n");
816 if (m_device.isImageRegistrationModeSupported(
817 openni::IMAGE_REGISTRATION_DEPTH_TO_COLOR) &&
818 m_streams[DEPTH_STREAM] && m_streams[DEPTH_STREAM]->isValid() &&
819 m_streams[COLOR_STREAM] && m_streams[COLOR_STREAM]->isValid())
824 if (m_device.setImageRegistrationMode(
825 openni::IMAGE_REGISTRATION_DEPTH_TO_COLOR) != openni::STATUS_OK)
827 m_log <<
" setImageRegistrationMode() Failed:"
828 << openni::OpenNI::getExtendedError() << endl;
832 m_log <<
" setImageRegistrationMode() Success" << endl;
837 m_log <<
" Device doesn't do image registration!" << endl;
842 m_streams[COLOR_STREAM]->disableAutoExposure();
843 printf(
"DBG: returned from disableAutoExposure()\n");
846 if (startStreams() ==
false)
855 bool COpenNI2Generic::CDevice::getNextFrameRGB(
857 bool& hardware_error)
864 openni::VideoFrameRef frame;
865 if (m_streams[COLOR_STREAM]->getFrame(
866 frame, timestamp, there_is_obs, hardware_error) ==
false)
870 copyFrame<openni::RGB888Pixel, mrpt::img::CImage>(frame,
img);
876 bool COpenNI2Generic::CDevice::getNextFrameD(
878 bool& hardware_error)
885 openni::VideoFrameRef frame;
886 if (m_streams[DEPTH_STREAM]->getFrame(
887 frame, timestamp, there_is_obs, hardware_error) ==
false)
891 copyFrame<openni::DepthPixel, mrpt::math::CMatrix>(frame,
img);
897 bool COpenNI2Generic::CDevice::getNextFrameRGBD(
899 bool& hardware_error)
903 there_is_obs =
false;
904 hardware_error =
false;
916 openni::VideoFrameRef frame[STREAM_TYPE_SIZE];
917 for (
int i = 0; i < STREAM_TYPE_SIZE; ++i)
919 if (!m_streams[i] || !m_streams[i]->isValid())
continue;
920 if (m_streams[i]->getFrame(
921 frame[i], tm, there_is_obs, hardware_error) ==
false)
925 if (there_is_obs ==
false || hardware_error ==
true)
931 const int width = frame[COLOR_STREAM].getWidth();
932 const int height = frame[COLOR_STREAM].getHeight();
933 if ((frame[DEPTH_STREAM].getWidth() !=
width) ||
936 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl
937 <<
" Both frames don't have the same size." << std::endl;
949 const char*
data[STREAM_TYPE_SIZE] = {
950 (
const char*)frame[COLOR_STREAM].getData(),
951 (
const char*)frame[DEPTH_STREAM].getData()};
952 const int step[STREAM_TYPE_SIZE] = {frame[COLOR_STREAM].getStrideInBytes(),
953 frame[DEPTH_STREAM].getStrideInBytes()};
955 for (
int yc = 0; yc <
height; ++yc)
957 const openni::RGB888Pixel* pRgb =
958 (
const openni::RGB888Pixel*)
data[COLOR_STREAM];
959 const openni::DepthPixel* pDepth =
960 (
const openni::DepthPixel*)
data[DEPTH_STREAM];
961 for (
int xc = 0; xc <
width; ++xc, ++pDepth, ++pRgb)
971 data[COLOR_STREAM] += step[COLOR_STREAM];
972 data[DEPTH_STREAM] += step[DEPTH_STREAM];
980 const openni::DeviceInfo& info, openni::PixelFormat rgb,
981 openni::PixelFormat
depth,
bool verbose)
983 return Ptr(
new CDevice(info, rgb,
depth, verbose));
986 bool COpenNI2Generic::CDevice::getSerialNumber(
std::string& sn)
991 if (isOpened ==
false)
993 rc = m_device.open(getInfo().getUri());
994 if (rc != openni::STATUS_OK)
996 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl
997 <<
" Failed to open device " << getInfo().getUri() <<
" "
998 << openni::OpenNI::getExtendedError() << std::endl;
1002 char serialNumber[16];
1003 rc = m_device.getProperty(ONI_DEVICE_PROPERTY_SERIAL_NUMBER, &serialNumber);
1004 if (rc != openni::STATUS_OK)
1006 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl
1007 <<
" Failed to getProperty(ONI_DEVICE_PROPERTY_SERIAL_NUMBER) "
1008 << getInfo().getUri() <<
" " << openni::OpenNI::getExtendedError()
1013 if (isOpened ==
false)
1020 bool COpenNI2Generic::CDevice::getSerialNumber(
unsigned int& sn)
1023 if (getSerialNumber(str) ==
false)
1027 std::stringstream sst;
1035 std::ostream& log,
bool verbose)
1038 m_strName(
"Unknown"),
1043 if (m_type == openni::SENSOR_COLOR)
1045 m_strName =
"openni::SENSOR_COLOR";
1047 else if (m_type == openni::SENSOR_DEPTH)
1049 m_strName =
"openni::SENSOR_DEPTH";
1051 else if (m_type == openni::SENSOR_IR)
1053 m_strName =
"openni::SENSOR_IR";
1057 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl
1058 <<
" Unknown SensorType -> " << m_type << std::endl;
1062 COpenNI2Generic::CDevice::CStream::~CStream() { destroy(); }
1063 bool COpenNI2Generic::CDevice::CStream::isMirrorSupported()
const
1065 if (isValid() ==
false)
1069 return m_stream.isPropertySupported(openni::STREAM_PROPERTY_MIRRORING);
1072 bool COpenNI2Generic::CDevice::CStream::setMirror(
bool flag)
1074 if (isValid() ==
false)
1076 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl
1077 <<
" " << getName() <<
" is not opened." << std::endl;
1080 if (m_stream.isPropertySupported(openni::STREAM_PROPERTY_MIRRORING) ==
1085 if (m_stream.setMirroringEnabled(flag) != openni::STATUS_OK)
1087 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl
1088 <<
" setMirroringEnabled() failed: "
1089 << openni::OpenNI::getExtendedError() << std::endl;
1095 bool COpenNI2Generic::CDevice::CStream::isValid()
const
1097 return m_stream.isValid();
1100 void COpenNI2Generic::CDevice::CStream::destroy() { m_stream.destroy(); }
1101 void COpenNI2Generic::CDevice::CStream::setCloseRange(
int&
value)
1105 " [CDevice::CStream::setCloseRange] entry with value=%d\n",
1107 m_stream.setProperty(XN_STREAM_PROPERTY_CLOSE_RANGE,
value);
1110 " [CDevice::CStream::setCloseRange] returned from "
1111 "mstream.setProperty()\n");
1112 m_stream.getProperty(XN_STREAM_PROPERTY_CLOSE_RANGE, &
value);
1115 " [CDevice::CStream::setCloseRange] returned from "
1116 "mstream.getProperty() ... value %d\n",
1120 bool COpenNI2Generic::CDevice::CStream::open(
int w,
int h,
int fps)
1123 if (m_type != openni::SENSOR_COLOR && m_type != openni::SENSOR_DEPTH &&
1124 m_type != openni::SENSOR_IR)
1126 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl
1127 <<
" Unknown SensorType -> " << m_type << std::endl;
1132 " [COpenNI2Generic::CDevice::CStream::open] opening sensor "
1133 "stream with m_type == %d\n",
1142 rc = m_stream.create(m_device, m_type);
1143 if (rc != openni::STATUS_OK)
1145 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl
1146 <<
" Couldn't find sensor " << m_strName <<
":"
1147 << openni::OpenNI::getExtendedError() << std::endl;
1148 if (m_type == openni::SENSOR_COLOR)
1150 m_type = openni::SENSOR_IR;
1151 m_strName =
"openni::SENSOR_IR";
1153 printf(
"DBG: changing type to SENSOR_IR (%d)\n", (
int)m_type);
1154 rc = m_stream.create(m_device, m_type);
1159 if (m_verbose) printf(
"returned OK from stream.create()\n");
1160 openni::VideoMode options = m_stream.getVideoMode();
1161 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl;
1162 m_log <<
" " << m_strName << std::endl;
1164 "Initial resolution (%d, %d) FPS %d Format %d",
1165 options.getResolutionX(), options.getResolutionY(),
1166 options.getFps(), options.getPixelFormat())
1168 if (m_verbose) printf(
"DBG: calling setONI2StreamMode()\n");
1169 if (setONI2StreamMode(m_stream,
w, h, fps, m_format) ==
false)
1171 m_log <<
" Can't find desired mode in the " << getName() << std::endl;
1175 if (m_verbose) printf(
"DBG: returned OK from setONI2StreamMode()\n");
1176 if (m_verbose) printf(
"DBG: calling stream.getVideoMode()\n");
1177 options = m_stream.getVideoMode();
1179 "-> (%d, %d) FPS %d Format %d",
1180 options.getResolutionX(), options.getResolutionY(),
1181 options.getFps(), options.getPixelFormat())
1185 " [COpenNI2Generic::CDevice::CStream::open] returning TRUE\n");
1191 if (isValid() ==
false)
1193 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl
1194 <<
" " << getName() <<
" is not opened." << std::endl;
1197 if (m_stream.start() != openni::STATUS_OK)
1199 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl
1200 <<
" Couldn't start " << getName()
1201 <<
" stream:" << openni::OpenNI::getExtendedError() << std::endl;
1208 COpenNI2Generic::CDevice::CStream::Ptr
1209 COpenNI2Generic::CDevice::CStream::create(
1211 openni::PixelFormat
format, std::ostream& log,
bool verbose)
1216 bool COpenNI2Generic::CDevice::CStream::getFrame(
1217 openni::VideoFrameRef& frame,
uint64_t& timestamp,
bool& there_is_obs,
1218 bool& hardware_error)
1220 there_is_obs =
false;
1221 hardware_error =
false;
1222 if (isValid() ==
false)
1227 if (rc != openni::STATUS_OK)
1229 hardware_error =
true;
1231 mrpt::format(
"Failed to grab frame from %s", getName().c_str());
1234 there_is_obs =
true;
1239 #endif // MRPT_HAS_OPENNI2