18 #include <mrpt/otherlibs/do_opencv_includes.h>
23 #if !defined(MRPT_OS_WINDOWS)
39 std::vector<stlplus::smart_ptr<COpenNI2Generic::CDevice> >
COpenNI2Generic::vDevices = std::vector<stlplus::smart_ptr<COpenNI2Generic::CDevice> >();
43 bool setONI2StreamMode(openni::VideoStream& stream,
int w,
int h,
int fps, openni::PixelFormat
format);
44 std::string oni2DevInfoStr(
const openni::DeviceInfo&
info,
int tab = 0);
45 bool cmpONI2Device(
const openni::DeviceInfo& i1,
const openni::DeviceInfo& i2);
58 m_rgb_format(openni::PIXEL_FORMAT_RGB888),
59 m_depth_format(openni::PIXEL_FORMAT_DEPTH_1_MM),
64 m_grab_3D_points(true)
66 const char * sVerbose = getenv(
"MRPT_HWDRIVERS_VERBOSE");
67 m_verbose = (sVerbose!=NULL) && atoi(sVerbose)!=0;
81 m_rgb_format(openni::PIXEL_FORMAT_RGB888),
82 m_depth_format(openni::PIXEL_FORMAT_DEPTH_1_MM),
87 m_grab_3D_points(true)
89 const char * sVerbose = getenv(
"MRPT_HWDRIVERS_VERBOSE");
90 m_verbose = (sVerbose!=NULL) && atoi(sVerbose)!=0;
92 if (open_streams_now) {
105 if(openni::OpenNI::initialize() != openni::STATUS_OK){
108 std::cerr <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" Initialized OpenNI2." << std::endl;
145 std::cerr << message;
154 openni::Array<openni::DeviceInfo> oni2InfoArray;
155 openni::OpenNI::enumerateDevices(&oni2InfoArray);
157 const size_t numDevices = oni2InfoArray.getSize();
162 std::set<int> newDevices;
163 for(
unsigned i=0; i < numDevices; i++){
164 const openni::DeviceInfo&
info = oni2InfoArray[i];
168 bool isExist =
false;
169 for(
unsigned int j = 0, j_end =
vDevices.size();j < j_end && isExist ==
false;++j){
174 if(isExist ==
false){
175 newDevices.insert(i);
180 const openni::DeviceInfo&
info = oni2InfoArray[*it];
185 if (device->getSerialNumber(sn)) {
192 showLog(
" No devices connected -> EXIT\n");
206 openni::OpenNI::shutdown();
218 return vDevices[sensor_id]->isOpen();
233 THROW_EXCEPTION(
"Sensor index is higher than the number of connected devices.")
242 if (
m_verbose) printf(
"[COpenNI2Generic] DBG: [%s] about to call vDevices[%d]->open()\n",__FUNCTION__,sensor_id);
247 showLog(
" open successfully.\n");
262 unsigned num_open_dev = 0;
263 for(
unsigned sensor_id=0; sensor_id <
vDevices.size(); sensor_id++)
265 unsigned int serialNum;
266 if(
vDevices[sensor_id]->getSerialNumber(serialNum) ==
false){
270 if (
m_verbose) printf(
"[COpenNI2Generic::openDevicesBySerialNum] checking device with serial '%d'\n",serialNum);
272 if(serial_required.find(serialNum) == serial_required.end()){
282 if (
m_verbose) printf(
"[COpenNI2Generic] DBG: [%s] about to call vDevices[%d]->open(%d,%d,%d)\n",
289 if (
m_verbose) printf(
"[COpenNI2Generic] DBG: [%s] now has %d devices open\n", __FUNCTION__,num_open_dev);
299 std::set<unsigned> serial_required;
300 serial_required.insert(SerialRequired);
306 for(
size_t i = 0, i_end =
vDevices.size();i < i_end;++i){
308 if(
vDevices[i]->getSerialNumber(sn) ==
false){
311 if(sn == SerialRequired){
331 THROW_EXCEPTION(
"Sensor index is higher than the number of connected devices.")
352 bool &hardware_error,
361 THROW_EXCEPTION(
"Sensor index is higher than the number of connected devices.")
387 bool &hardware_error,
396 THROW_EXCEPTION(
"Sensor index is higher than the number of connected devices.")
420 bool &hardware_error,
429 THROW_EXCEPTION(
"Sensor index is higher than the number of connected devices.")
445 if(
isOpen(sensor_id) ==
false){
457 if(
isOpen(sensor_id) ==
false){
476 bool setONI2StreamMode(openni::VideoStream& stream,
int w,
int h,
int fps, openni::PixelFormat
format){
479 const openni::Array<openni::VideoMode>& modes = stream.getSensorInfo().getSupportedVideoModes();
480 for(
int i = 0, i_end = modes.getSize();i < i_end;++i){
482 if(modes[i].getResolutionX() !=
w){
485 if(modes[i].getResolutionY() != h){
488 if(modes[i].getFps() != fps){
491 if(modes[i].getPixelFormat() !=
format){
495 if(rc != openni::STATUS_OK){
504 std::stringstream sst;
506 for(
int i = 0;i < tab;++i){
509 sst << space <<
"name=" <<
info.getName() << std::endl;
510 sst << space <<
"uri=" <<
info.getUri() << std::endl;
511 sst << space <<
"vendor=" <<
info.getVendor() << std::endl;
512 sst << space <<
"product=" <<
info.getUsbProductId();
516 bool cmpONI2Device(
const openni::DeviceInfo& i1,
const openni::DeviceInfo& i2){
517 return (strcmp(i1.getUri(), i2.getUri()) == 0);
520 COpenNI2Generic::CDevice::CDevice(
const openni::DeviceInfo&
info, openni::PixelFormat rgb, openni::PixelFormat
depth,
bool verbose)
521 :m_info(
info), m_mirror(true), m_verbose(verbose)
523 m_streams[COLOR_STREAM] = CStream::create(m_device, openni::SENSOR_COLOR, rgb , m_log,
m_verbose);
524 m_streams[IR_STREAM] = CStream::create(m_device, openni::SENSOR_IR, rgb , m_log,
m_verbose);
525 m_streams[DEPTH_STREAM] = CStream::create(m_device, openni::SENSOR_DEPTH,
depth, m_log,
m_verbose);
528 COpenNI2Generic::CDevice::~CDevice(){
532 bool COpenNI2Generic::CDevice::synchMirrorMode(){
535 for(
int i = 0;i < STREAM_TYPE_SIZE;++i){
536 if (!m_streams[i])
continue;
539 mirror_support = m_streams[i]->isMirrorSupported();
540 }
catch(std::logic_error& e){
543 if(mirror_support ==
false){
544 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl;
545 m_log <<
" openni::STREAM_PROPERTY_MIRRORING is not supported on " << m_streams[i]->getName() <<
"." << std::endl;
546 m_log <<
" We assume this is MS Kinect and taken images are inverted to right and left." << std::endl;
553 for(
int i = 0;i < STREAM_TYPE_SIZE;++i){
554 if (!m_streams[i])
continue;
555 if(m_streams[i]->isMirrorSupported() ==
false){
558 if(m_streams[i]->setMirror(m_mirror) ==
false){
565 bool COpenNI2Generic::CDevice::startStreams(){
568 for(
int i = 0;i < STREAM_TYPE_SIZE;++i){
569 if (!m_streams[i])
continue;
570 if (
m_verbose) printf(
" [%s] calling m_streams[%d]->start()\n",__FUNCTION__,i);
571 if(m_streams[i]->
start() ==
false){
572 if (
m_verbose) printf(
" [%s] m_streams[%d]->start() returned FALSE!\n",__FUNCTION__,i);
577 if (
m_verbose) printf(
" [%s] m_streams[%d]->start() returned TRUE\n",__FUNCTION__,i);
579 if (
m_verbose) printf(
" [COpenNI2Generic::CDevice::startStreams()] %d streams were started.\n", num_ok);
584 bool COpenNI2Generic::CDevice::isOpen()
const{
585 return (m_streams[COLOR_STREAM] && m_streams[COLOR_STREAM]->isValid()) ||
586 (m_streams[DEPTH_STREAM] && m_streams[DEPTH_STREAM]->isValid());
589 void COpenNI2Generic::CDevice::close(){
590 for(
int i = 0;i < STREAM_TYPE_SIZE;++i){
591 if (!m_streams[i])
continue;
592 m_streams[i]->destroy();
597 bool COpenNI2Generic::CDevice::open(
int w,
int h,
int fps){
599 if (
m_verbose) printf(
" [COpenNI2Generic::CDevice::open()] Called with w=%i h=%i fps=%i\n",
w,h,fps);
603 if(rc != openni::STATUS_OK){
604 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" Failed to open device " << getInfo().getUri() <<
" " << openni::OpenNI::getExtendedError() << std::endl;
607 for(
int i = 0;i < STREAM_TYPE_SIZE;++i){
608 if(!m_streams[i])
continue;
609 if (
m_verbose) printf(
" [%s] calling m_streams[%d]->open()\n",__FUNCTION__,i);
611 if(m_streams[i]->
open(
w, h, fps) ==
false)
613 if (
m_verbose) printf(
" [%s] m_streams[%d]->open() returned FALSE\n",__FUNCTION__,i);
616 if (
m_verbose) printf(
" [%s] m_streams[%d]->open() returned OK\n",__FUNCTION__,i);
619 if(synchMirrorMode() ==
false){
624 if (m_streams[DEPTH_STREAM]) {
626 m_streams[DEPTH_STREAM]->setCloseRange(CloseRange);
627 m_log <<
" Close range: " << (CloseRange?
"On" :
"Off") << std::endl;
630 if (
m_verbose) printf(
" DBG: checking if imageRegistrationMode is supported\n");
631 if(m_device.isImageRegistrationModeSupported(openni::IMAGE_REGISTRATION_DEPTH_TO_COLOR) &&
632 m_streams[DEPTH_STREAM] && m_streams[DEPTH_STREAM]->isValid() &&
633 m_streams[COLOR_STREAM] && m_streams[COLOR_STREAM]->isValid() )
636 if(m_device.setImageRegistrationMode(openni::IMAGE_REGISTRATION_DEPTH_TO_COLOR) != openni::STATUS_OK){
637 m_log <<
" setImageRegistrationMode() Failed:" << openni::OpenNI::getExtendedError() << endl;
639 m_log <<
" setImageRegistrationMode() Success" << endl;
642 m_log <<
" Device doesn't do image registration!" << endl;
647 m_streams[COLOR_STREAM]->disableAutoExposure();
648 printf(
"DBG: returned from disableAutoExposure()\n");
651 if(startStreams() ==
false){
664 openni::VideoFrameRef frame;
665 if(m_streams[COLOR_STREAM]->getFrame(frame, timestamp, there_is_obs, hardware_error) ==
false){
668 copyFrame<openni::RGB888Pixel, mrpt::utils::CImage>(frame,
img);
679 openni::VideoFrameRef frame;
680 if(m_streams[DEPTH_STREAM]->getFrame(frame, timestamp, there_is_obs, hardware_error) ==
false){
683 copyFrame<openni::DepthPixel, mrpt::math::CMatrix>(frame,
img);
692 there_is_obs =
false;
693 hardware_error =
false;
703 openni::VideoFrameRef frame[STREAM_TYPE_SIZE];
704 for(
int i = 0;i < STREAM_TYPE_SIZE;++i){
705 if (!m_streams[i] || !m_streams[i]->isValid())
continue;
706 if(m_streams[i]->getFrame(frame[i], tm, there_is_obs, hardware_error) ==
false){
709 if(there_is_obs ==
false || hardware_error ==
true){
714 const int width = frame[COLOR_STREAM].getWidth();
715 const int height = frame[COLOR_STREAM].getHeight();
717 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" Both frames don't have the same size." << std::endl;
729 const char*
data[STREAM_TYPE_SIZE] =
731 (
const char*)frame[COLOR_STREAM].getData(),
732 (
const char*)frame[DEPTH_STREAM].getData()
734 const int step[STREAM_TYPE_SIZE] =
736 frame[COLOR_STREAM].getStrideInBytes(),
737 frame[DEPTH_STREAM].getStrideInBytes()
740 for (
int yc = 0; yc <
height; ++yc){
741 const openni::RGB888Pixel* pRgb = (
const openni::RGB888Pixel*)
data[COLOR_STREAM];
742 const openni::DepthPixel * pDepth = (
const openni::DepthPixel *)
data[DEPTH_STREAM];
743 for (
int xc = 0; xc <
width; ++xc, ++pDepth, ++pRgb){
751 data[COLOR_STREAM] += step[COLOR_STREAM];
752 data[DEPTH_STREAM] += step[DEPTH_STREAM];
763 bool COpenNI2Generic::CDevice::getSerialNumber(
std::string& sn){
767 if(isOpened ==
false){
768 rc = m_device.open(getInfo().getUri());
769 if(rc != openni::STATUS_OK){
770 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" Failed to open device " << getInfo().getUri() <<
" " << openni::OpenNI::getExtendedError() << std::endl;
774 char serialNumber[16];
775 rc = m_device.getProperty(ONI_DEVICE_PROPERTY_SERIAL_NUMBER, &serialNumber);
776 if(rc != openni::STATUS_OK){
777 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" Failed to getProperty(ONI_DEVICE_PROPERTY_SERIAL_NUMBER) " << getInfo().getUri() <<
" " << openni::OpenNI::getExtendedError() << std::endl;
781 if(isOpened ==
false){
787 bool COpenNI2Generic::CDevice::getSerialNumber(
unsigned int& sn){
789 if(getSerialNumber(str) ==
false){
792 std::stringstream sst;
798 COpenNI2Generic::CDevice::CStream::CStream(openni::Device& device,
openni::SensorType type, openni::PixelFormat
format, std::ostream& log,
bool verbose)
799 :m_log(log), m_device(device), m_strName(
"Unknown"), m_type(
type), m_format(
format),
m_verbose(verbose)
801 if(m_type == openni::SENSOR_COLOR){
802 m_strName =
"openni::SENSOR_COLOR";
803 }
else if(m_type == openni::SENSOR_DEPTH){
804 m_strName =
"openni::SENSOR_DEPTH";
805 }
else if(m_type == openni::SENSOR_IR){
806 m_strName =
"openni::SENSOR_IR";
808 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" Unknown SensorType -> " << m_type << std::endl;
812 COpenNI2Generic::CDevice::CStream::~CStream(){
816 bool COpenNI2Generic::CDevice::CStream::isMirrorSupported()
const{
817 if(isValid() ==
false){
820 return m_stream.isPropertySupported(openni::STREAM_PROPERTY_MIRRORING);
823 bool COpenNI2Generic::CDevice::CStream::setMirror(
bool flag){
824 if(isValid() ==
false){
825 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" " << getName() <<
" is not opened." << std::endl;
828 if(m_stream.isPropertySupported(openni::STREAM_PROPERTY_MIRRORING) ==
false){
831 if(m_stream.setMirroringEnabled(flag) != openni::STATUS_OK){
832 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" setMirroringEnabled() failed: " << openni::OpenNI::getExtendedError() << std::endl;
838 bool COpenNI2Generic::CDevice::CStream::isValid()
const{
839 return m_stream.isValid();
842 void COpenNI2Generic::CDevice::CStream::destroy(){
846 void COpenNI2Generic::CDevice::CStream::setCloseRange(
int&
value){
847 if (m_verbose) printf(
" [CDevice::CStream::setCloseRange] entry with value=%d\n",
value);
848 m_stream.setProperty(XN_STREAM_PROPERTY_CLOSE_RANGE,
value);
849 if (m_verbose) printf(
" [CDevice::CStream::setCloseRange] returned from mstream.setProperty()\n");
850 m_stream.getProperty(XN_STREAM_PROPERTY_CLOSE_RANGE, &
value);
851 if (m_verbose) printf(
" [CDevice::CStream::setCloseRange] returned from mstream.getProperty() ... value %d\n",
value);
854 bool COpenNI2Generic::CDevice::CStream::open(
int w,
int h,
int fps){
856 if(m_type != openni::SENSOR_COLOR && m_type != openni::SENSOR_DEPTH && m_type != openni::SENSOR_IR){
857 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" Unknown SensorType -> " << m_type << std::endl;
860 if (m_verbose) printf(
" [COpenNI2Generic::CDevice::CStream::open] opening sensor stream with m_type == %d\n",(
int)m_type);
867 rc = m_stream.create(m_device, m_type);
868 if(rc != openni::STATUS_OK){
869 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" Couldn't find sensor "
870 << m_strName <<
":" << openni::OpenNI::getExtendedError() << std::endl;
871 if(m_type == openni::SENSOR_COLOR) {
872 m_type = openni::SENSOR_IR;
873 m_strName=
"openni::SENSOR_IR";
874 if (m_verbose) printf(
"DBG: changing type to SENSOR_IR (%d)\n",(
int)m_type);
875 rc = m_stream.create(m_device, m_type);
880 if (m_verbose) printf(
"returned OK from stream.create()\n");
881 openni::VideoMode options = m_stream.getVideoMode();
882 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl;
883 m_log <<
" " << m_strName << std::endl;
884 m_log <<
" " <<
mrpt::format(
"Initial resolution (%d, %d) FPS %d Format %d", options.getResolutionX(), options.getResolutionY(), options.getFps(), options.getPixelFormat()) << std::endl;
885 if (m_verbose) printf(
"DBG: calling setONI2StreamMode()\n");
886 if(setONI2StreamMode(m_stream,
w, h, fps, m_format) ==
false){
887 m_log <<
" Can't find desired mode in the " << getName() << std::endl;
891 if (m_verbose) printf(
"DBG: returned OK from setONI2StreamMode()\n");
892 if (m_verbose) printf(
"DBG: calling stream.getVideoMode()\n");
893 options = m_stream.getVideoMode();
894 m_log <<
" " <<
mrpt::format(
"-> (%d, %d) FPS %d Format %d", options.getResolutionX(), options.getResolutionY(), options.getFps(), options.getPixelFormat()) << std::endl;
895 if (m_verbose) printf(
" [COpenNI2Generic::CDevice::CStream::open] returning TRUE\n");
900 if(isValid() ==
false){
901 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" " << getName() <<
" is not opened." << std::endl;
904 if(m_stream.start() != openni::STATUS_OK){
905 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" Couldn't start " << getName() <<
" stream:" << openni::OpenNI::getExtendedError() << std::endl;
912 COpenNI2Generic::CDevice::CStream::Ptr COpenNI2Generic::CDevice::CStream::create(openni::Device& device,
openni::SensorType type, openni::PixelFormat
format, std::ostream& log,
bool verbose){
913 return Ptr(
new CStream(device,
type,
format, log,verbose));
916 bool COpenNI2Generic::CDevice::CStream::getFrame(openni::VideoFrameRef& frame,
uint64_t ×tamp,
bool &there_is_obs,
bool &hardware_error)
918 there_is_obs =
false;
919 hardware_error =
false;
920 if(isValid() ==
false){
924 if(rc != openni::STATUS_OK){
925 hardware_error =
true;
double getHeight(const TPolygon3D &p, const TPoint3D &c)
stlplus::smart_ptr< CDevice > Ptr
bool isOpen(const unsigned sensor_id) const
Whether there is a working connection to the sensor.
void showLog(const std::string &message) const
void close(unsigned sensor_id=0)
Close the connection to the sensor (no need to call it manually unless desired for some reason,...
bool getDeviceIDFromSerialNum(const unsigned int SerialRequired, int &sensor_id) const
Get the ID of the device corresponding to 'SerialRequired'.
int getConnectedDevices()
Get a list of the connected OpenNI2 sensors.
bool getColorSensorParam(mrpt::utils::TCamera ¶m, unsigned sensor_id=0) const
class HWDRIVERS_IMPEXP CDevice
The list of available devices.
COpenNI2Generic()
Default ctor (width=640, height=480, fps=30)
unsigned int openDevicesBySerialNum(const std::set< unsigned > &vSerialRequired)
Open a set of RGBD devices specified by their serial number.
void getNextFrameD(mrpt::math::CMatrix &depth_img, uint64_t ×tamp, bool &there_is_obs, bool &hardware_error, unsigned sensor_id=0)
The main data retrieving function, to be called after calling loadConfig() and initialize().
void getNextFrameRGBD(mrpt::obs::CObservation3DRangeScan &out_obs, bool &there_is_obs, bool &hardware_error, unsigned sensor_id=0)
The main data retrieving function, to be called after calling loadConfig() and initialize().
static std::vector< stlplus::smart_ptr< CDevice > > vDevices
bool start()
Open all sensor streams (normally called automatically at constructor, no need to call it manually).
void kill()
Kill the OpenNI2 driver.
void getNextFrameRGB(mrpt::utils::CImage &rgb_img, uint64_t ×tamp, bool &there_is_obs, bool &hardware_error, unsigned sensor_id=0)
The main data retrieving function, to be called after calling loadConfig() and initialize().
~COpenNI2Generic()
Default ctor.
void setVerbose(bool verbose)
int m_width
The same options (width, height and fps) are set for all the sensors.
int getNumDevices() const
The number of available devices at initialization.
void open(unsigned sensor_id=0)
Try to open the camera (all the parameters [resolution,fps,...] must be set before calling this) - us...
unsigned int openDeviceBySerial(const unsigned int SerialRequired)
Open a RGBD device specified by its serial number.
bool getDepthSensorParam(mrpt::utils::TCamera ¶m, unsigned sensor_id=0) const
This class is a "CSerializable" wrapper for "CMatrixFloat".
Declares a class derived from "CObservation" that encapsules a 3D range scan measurement,...
bool hasConfidenceImage
true means the field confidenceImage contains valid data
bool hasIntensityImage
true means the field intensityImage contains valid data
bool hasPoints3D
true means the field points3D contains valid data.
bool hasRangeImage
true means the field rangeImage contains valid data
mrpt::math::CMatrix rangeImage
If hasRangeImage=true, a matrix of floats with the range data as captured by the camera (in meters)
mrpt::utils::CImage intensityImage
If hasIntensityImage=true, a color or gray-level intensity image of the same size than "rangeImage".
bool range_is_depth
true: Kinect-like ranges: entries of rangeImage are distances along the +X axis; false: Ranges in ran...
mrpt::system::TTimeStamp timestamp
The associated UTC time-stamp. Where available, this should contain the accurate satellite-based time...
A class for storing images as grayscale or RGB bitmaps.
Structure to hold the parameters of a pinhole camera model.
const Scalar * const_iterator
GLint GLint GLsizei GLsizei GLsizei depth
GLubyte GLubyte GLubyte GLubyte w
GLsizei GLsizei GLenum GLenum const GLvoid * data
GLuint GLuint GLsizei GLenum type
GLenum GLsizei GLsizei height
GLenum GLsizei GLenum format
GLsizei const GLfloat * value
GLsizei const GLchar ** string
void BASE_IMPEXP sleep(int time_ms) MRPT_NO_THROWS
An OS-independent method for sending the current thread to "sleep" for a given period of time.
uint64_t TTimeStamp
A system independent time type, it holds the the number of 100-nanosecond intervals since January 1,...
mrpt::system::TTimeStamp BASE_IMPEXP getCurrentTime()
Returns the current (UTC) system time.
#define THROW_EXCEPTION(msg)
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
Contains classes for various device interfaces.
This namespace contains representation of robot actions and observations.
This namespace provides multitask, synchronization utilities.
This namespace provides a OS-independent interface to many useful functions: filenames manipulation,...
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
unsigned __int64 uint64_t