18 #include <mrpt/otherlibs/do_opencv_includes.h>
26 #if !defined(MRPT_OS_WINDOWS)
42 std::vector<std::shared_ptr<COpenNI2Generic::CDevice> >
vDevices;
47 bool setONI2StreamMode(openni::VideoStream& stream,
int w,
int h,
int fps, openni::PixelFormat
format);
48 std::string oni2DevInfoStr(
const openni::DeviceInfo&
info,
int tab = 0);
49 bool cmpONI2Device(
const openni::DeviceInfo& i1,
const openni::DeviceInfo& i2);
65 m_rgb_format(openni::PIXEL_FORMAT_RGB888),
66 m_depth_format(openni::PIXEL_FORMAT_DEPTH_1_MM),
71 m_grab_3D_points(true)
73 const char * sVerbose = getenv(
"MRPT_HWDRIVERS_VERBOSE");
74 m_verbose = (sVerbose!=NULL) && atoi(sVerbose)!=0;
88 m_rgb_format(openni::PIXEL_FORMAT_RGB888),
89 m_depth_format(openni::PIXEL_FORMAT_DEPTH_1_MM),
94 m_grab_3D_points(true)
96 const char * sVerbose = getenv(
"MRPT_HWDRIVERS_VERBOSE");
97 m_verbose = (sVerbose!=NULL) && atoi(sVerbose)!=0;
99 if (open_streams_now) {
100 if (!this->
start()) {
112 if(openni::OpenNI::initialize() != openni::STATUS_OK){
115 std::cerr <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" Initialized OpenNI2." << std::endl;
137 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
153 std::cerr << message;
162 openni::Array<openni::DeviceInfo> oni2InfoArray;
163 openni::OpenNI::enumerateDevices(&oni2InfoArray);
165 const size_t numDevices = oni2InfoArray.getSize();
170 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
171 std::set<int> newDevices;
172 for(
unsigned i=0; i < numDevices; i++){
173 const openni::DeviceInfo&
info = oni2InfoArray[i];
177 bool isExist =
false;
178 for(
unsigned int j = 0, j_end =
vDevices.size();j < j_end && isExist ==
false;++j){
183 if(isExist ==
false){
184 newDevices.insert(i);
189 const openni::DeviceInfo&
info = oni2InfoArray[*it];
194 if (device->getSerialNumber(sn)) {
201 showLog(
" No devices connected -> EXIT\n");
214 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
216 openni::OpenNI::shutdown();
228 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
229 return vDevices[sensor_id]->isOpen();
239 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
245 THROW_EXCEPTION(
"Sensor index is higher than the number of connected devices.")
254 if (
m_verbose) printf(
"[COpenNI2Generic] DBG: [%s] about to call vDevices[%d]->open()\n",__FUNCTION__,sensor_id);
259 showLog(
" open successfully.\n");
273 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
275 unsigned num_open_dev = 0;
276 for(
unsigned sensor_id=0; sensor_id <
vDevices.size(); sensor_id++)
278 unsigned int serialNum;
279 if(
vDevices[sensor_id]->getSerialNumber(serialNum) ==
false){
283 if (
m_verbose) printf(
"[COpenNI2Generic::openDevicesBySerialNum] checking device with serial '%d'\n",serialNum);
285 if(serial_required.find(serialNum) == serial_required.end()){
295 if (
m_verbose) printf(
"[COpenNI2Generic] DBG: [%s] about to call vDevices[%d]->open(%d,%d,%d)\n",
302 if (
m_verbose) printf(
"[COpenNI2Generic] DBG: [%s] now has %d devices open\n", __FUNCTION__,num_open_dev);
312 std::set<unsigned> serial_required;
313 serial_required.insert(SerialRequired);
319 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
320 for(
size_t i = 0, i_end =
vDevices.size();i < i_end;++i){
322 if(
vDevices[i]->getSerialNumber(sn) ==
false){
325 if(sn == SerialRequired){
340 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
346 THROW_EXCEPTION(
"Sensor index is higher than the number of connected devices.")
367 bool &hardware_error,
376 THROW_EXCEPTION(
"Sensor index is higher than the number of connected devices.")
402 bool &hardware_error,
411 THROW_EXCEPTION(
"Sensor index is higher than the number of connected devices.")
435 bool &hardware_error,
444 THROW_EXCEPTION(
"Sensor index is higher than the number of connected devices.")
460 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
461 if(
isOpen(sensor_id) ==
false){
473 std::lock_guard<std::recursive_mutex> lock(
vDevices_mx);
474 if(
isOpen(sensor_id) ==
false){
493 bool setONI2StreamMode(openni::VideoStream& stream,
int w,
int h,
int fps, openni::PixelFormat
format){
496 const openni::Array<openni::VideoMode>& modes = stream.getSensorInfo().getSupportedVideoModes();
497 for(
int i = 0, i_end = modes.getSize();i < i_end;++i){
499 if(modes[i].getResolutionX() !=
w){
502 if(modes[i].getResolutionY() != h){
505 if(modes[i].getFps() != fps){
508 if(modes[i].getPixelFormat() !=
format){
512 if(rc != openni::STATUS_OK){
521 std::stringstream sst;
523 for(
int i = 0;i < tab;++i){
526 sst << space <<
"name=" <<
info.getName() << std::endl;
527 sst << space <<
"uri=" <<
info.getUri() << std::endl;
528 sst << space <<
"vendor=" <<
info.getVendor() << std::endl;
529 sst << space <<
"product=" <<
info.getUsbProductId();
533 bool cmpONI2Device(
const openni::DeviceInfo& i1,
const openni::DeviceInfo& i2){
534 return (strcmp(i1.getUri(), i2.getUri()) == 0);
537 COpenNI2Generic::CDevice::CDevice(
const openni::DeviceInfo&
info, openni::PixelFormat rgb, openni::PixelFormat
depth,
bool verbose)
538 :m_info(
info), m_mirror(true), m_verbose(verbose)
540 m_streams[COLOR_STREAM] = CStream::create(m_device, openni::SENSOR_COLOR, rgb , m_log,
m_verbose);
541 m_streams[IR_STREAM] = CStream::create(m_device, openni::SENSOR_IR, rgb , m_log,
m_verbose);
542 m_streams[DEPTH_STREAM] = CStream::create(m_device, openni::SENSOR_DEPTH,
depth, m_log,
m_verbose);
545 COpenNI2Generic::CDevice::~CDevice(){
549 bool COpenNI2Generic::CDevice::synchMirrorMode(){
552 for(
int i = 0;i < STREAM_TYPE_SIZE;++i){
553 if (!m_streams[i])
continue;
556 mirror_support = m_streams[i]->isMirrorSupported();
557 }
catch(std::logic_error& e){
560 if(mirror_support ==
false){
561 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl;
562 m_log <<
" openni::STREAM_PROPERTY_MIRRORING is not supported on " << m_streams[i]->getName() <<
"." << std::endl;
563 m_log <<
" We assume this is MS Kinect and taken images are inverted to right and left." << std::endl;
570 for(
int i = 0;i < STREAM_TYPE_SIZE;++i){
571 if (!m_streams[i])
continue;
572 if(m_streams[i]->isMirrorSupported() ==
false){
575 if(m_streams[i]->setMirror(m_mirror) ==
false){
582 bool COpenNI2Generic::CDevice::startStreams(){
585 for(
int i = 0;i < STREAM_TYPE_SIZE;++i){
586 if (!m_streams[i])
continue;
587 if (
m_verbose) printf(
" [%s] calling m_streams[%d]->start()\n",__FUNCTION__,i);
588 if(m_streams[i]->
start() ==
false){
589 if (
m_verbose) printf(
" [%s] m_streams[%d]->start() returned FALSE!\n",__FUNCTION__,i);
594 if (
m_verbose) printf(
" [%s] m_streams[%d]->start() returned TRUE\n",__FUNCTION__,i);
596 if (
m_verbose) printf(
" [COpenNI2Generic::CDevice::startStreams()] %d streams were started.\n", num_ok);
601 bool COpenNI2Generic::CDevice::isOpen()
const{
602 return (m_streams[COLOR_STREAM] && m_streams[COLOR_STREAM]->isValid()) ||
603 (m_streams[DEPTH_STREAM] && m_streams[DEPTH_STREAM]->isValid());
606 void COpenNI2Generic::CDevice::close(){
607 for(
int i = 0;i < STREAM_TYPE_SIZE;++i){
608 if (!m_streams[i])
continue;
609 m_streams[i]->destroy();
614 bool COpenNI2Generic::CDevice::open(
int w,
int h,
int fps){
616 if (
m_verbose) printf(
" [COpenNI2Generic::CDevice::open()] Called with w=%i h=%i fps=%i\n",
w,h,fps);
620 if(rc != openni::STATUS_OK){
621 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" Failed to open device " << getInfo().getUri() <<
" " << openni::OpenNI::getExtendedError() << std::endl;
624 for(
int i = 0;i < STREAM_TYPE_SIZE;++i){
625 if(!m_streams[i])
continue;
626 if (
m_verbose) printf(
" [%s] calling m_streams[%d]->open()\n",__FUNCTION__,i);
628 if(m_streams[i]->
open(
w, h, fps) ==
false)
630 if (
m_verbose) printf(
" [%s] m_streams[%d]->open() returned FALSE\n",__FUNCTION__,i);
633 if (
m_verbose) printf(
" [%s] m_streams[%d]->open() returned OK\n",__FUNCTION__,i);
636 if(synchMirrorMode() ==
false){
641 if (m_streams[DEPTH_STREAM]) {
643 m_streams[DEPTH_STREAM]->setCloseRange(CloseRange);
644 m_log <<
" Close range: " << (CloseRange?
"On" :
"Off") << std::endl;
647 if (
m_verbose) printf(
" DBG: checking if imageRegistrationMode is supported\n");
648 if(m_device.isImageRegistrationModeSupported(openni::IMAGE_REGISTRATION_DEPTH_TO_COLOR) &&
649 m_streams[DEPTH_STREAM] && m_streams[DEPTH_STREAM]->isValid() &&
650 m_streams[COLOR_STREAM] && m_streams[COLOR_STREAM]->isValid() )
653 if(m_device.setImageRegistrationMode(openni::IMAGE_REGISTRATION_DEPTH_TO_COLOR) != openni::STATUS_OK){
654 m_log <<
" setImageRegistrationMode() Failed:" << openni::OpenNI::getExtendedError() << endl;
656 m_log <<
" setImageRegistrationMode() Success" << endl;
659 m_log <<
" Device doesn't do image registration!" << endl;
664 m_streams[COLOR_STREAM]->disableAutoExposure();
665 printf(
"DBG: returned from disableAutoExposure()\n");
668 if(startStreams() ==
false){
681 openni::VideoFrameRef frame;
682 if(m_streams[COLOR_STREAM]->getFrame(frame, timestamp, there_is_obs, hardware_error) ==
false){
685 copyFrame<openni::RGB888Pixel, mrpt::utils::CImage>(frame,
img);
696 openni::VideoFrameRef frame;
697 if(m_streams[DEPTH_STREAM]->getFrame(frame, timestamp, there_is_obs, hardware_error) ==
false){
700 copyFrame<openni::DepthPixel, mrpt::math::CMatrix>(frame,
img);
709 there_is_obs =
false;
710 hardware_error =
false;
720 openni::VideoFrameRef frame[STREAM_TYPE_SIZE];
721 for(
int i = 0;i < STREAM_TYPE_SIZE;++i){
722 if (!m_streams[i] || !m_streams[i]->isValid())
continue;
723 if(m_streams[i]->getFrame(frame[i], tm, there_is_obs, hardware_error) ==
false){
726 if(there_is_obs ==
false || hardware_error ==
true){
731 const int width = frame[COLOR_STREAM].getWidth();
732 const int height = frame[COLOR_STREAM].getHeight();
734 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" Both frames don't have the same size." << std::endl;
746 const char*
data[STREAM_TYPE_SIZE] =
748 (
const char*)frame[COLOR_STREAM].getData(),
749 (
const char*)frame[DEPTH_STREAM].getData()
751 const int step[STREAM_TYPE_SIZE] =
753 frame[COLOR_STREAM].getStrideInBytes(),
754 frame[DEPTH_STREAM].getStrideInBytes()
757 for (
int yc = 0; yc <
height; ++yc){
758 const openni::RGB888Pixel* pRgb = (
const openni::RGB888Pixel*)
data[COLOR_STREAM];
759 const openni::DepthPixel * pDepth = (
const openni::DepthPixel *)
data[DEPTH_STREAM];
760 for (
int xc = 0; xc <
width; ++xc, ++pDepth, ++pRgb){
768 data[COLOR_STREAM] += step[COLOR_STREAM];
769 data[DEPTH_STREAM] += step[DEPTH_STREAM];
780 bool COpenNI2Generic::CDevice::getSerialNumber(
std::string& sn){
784 if(isOpened ==
false){
785 rc = m_device.open(getInfo().getUri());
786 if(rc != openni::STATUS_OK){
787 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" Failed to open device " << getInfo().getUri() <<
" " << openni::OpenNI::getExtendedError() << std::endl;
791 char serialNumber[16];
792 rc = m_device.getProperty(ONI_DEVICE_PROPERTY_SERIAL_NUMBER, &serialNumber);
793 if(rc != openni::STATUS_OK){
794 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" Failed to getProperty(ONI_DEVICE_PROPERTY_SERIAL_NUMBER) " << getInfo().getUri() <<
" " << openni::OpenNI::getExtendedError() << std::endl;
798 if(isOpened ==
false){
804 bool COpenNI2Generic::CDevice::getSerialNumber(
unsigned int& sn){
806 if(getSerialNumber(str) ==
false){
809 std::stringstream sst;
815 COpenNI2Generic::CDevice::CStream::CStream(openni::Device& device,
openni::SensorType type, openni::PixelFormat
format, std::ostream& log,
bool verbose)
816 :m_log(log), m_device(device), m_strName(
"Unknown"), m_type(
type), m_format(
format),
m_verbose(verbose)
818 if(m_type == openni::SENSOR_COLOR){
819 m_strName =
"openni::SENSOR_COLOR";
820 }
else if(m_type == openni::SENSOR_DEPTH){
821 m_strName =
"openni::SENSOR_DEPTH";
822 }
else if(m_type == openni::SENSOR_IR){
823 m_strName =
"openni::SENSOR_IR";
825 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" Unknown SensorType -> " << m_type << std::endl;
829 COpenNI2Generic::CDevice::CStream::~CStream(){
833 bool COpenNI2Generic::CDevice::CStream::isMirrorSupported()
const{
834 if(isValid() ==
false){
837 return m_stream.isPropertySupported(openni::STREAM_PROPERTY_MIRRORING);
840 bool COpenNI2Generic::CDevice::CStream::setMirror(
bool flag){
841 if(isValid() ==
false){
842 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" " << getName() <<
" is not opened." << std::endl;
845 if(m_stream.isPropertySupported(openni::STREAM_PROPERTY_MIRRORING) ==
false){
848 if(m_stream.setMirroringEnabled(flag) != openni::STATUS_OK){
849 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" setMirroringEnabled() failed: " << openni::OpenNI::getExtendedError() << std::endl;
855 bool COpenNI2Generic::CDevice::CStream::isValid()
const{
856 return m_stream.isValid();
859 void COpenNI2Generic::CDevice::CStream::destroy(){
863 void COpenNI2Generic::CDevice::CStream::setCloseRange(
int&
value){
864 if (m_verbose) printf(
" [CDevice::CStream::setCloseRange] entry with value=%d\n",
value);
865 m_stream.setProperty(XN_STREAM_PROPERTY_CLOSE_RANGE,
value);
866 if (m_verbose) printf(
" [CDevice::CStream::setCloseRange] returned from mstream.setProperty()\n");
867 m_stream.getProperty(XN_STREAM_PROPERTY_CLOSE_RANGE, &
value);
868 if (m_verbose) printf(
" [CDevice::CStream::setCloseRange] returned from mstream.getProperty() ... value %d\n",
value);
871 bool COpenNI2Generic::CDevice::CStream::open(
int w,
int h,
int fps){
873 if(m_type != openni::SENSOR_COLOR && m_type != openni::SENSOR_DEPTH && m_type != openni::SENSOR_IR){
874 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" Unknown SensorType -> " << m_type << std::endl;
877 if (m_verbose) printf(
" [COpenNI2Generic::CDevice::CStream::open] opening sensor stream with m_type == %d\n",(
int)m_type);
884 rc = m_stream.create(m_device, m_type);
885 if(rc != openni::STATUS_OK){
886 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" Couldn't find sensor "
887 << m_strName <<
":" << openni::OpenNI::getExtendedError() << std::endl;
888 if(m_type == openni::SENSOR_COLOR) {
889 m_type = openni::SENSOR_IR;
890 m_strName=
"openni::SENSOR_IR";
891 if (m_verbose) printf(
"DBG: changing type to SENSOR_IR (%d)\n",(
int)m_type);
892 rc = m_stream.create(m_device, m_type);
897 if (m_verbose) printf(
"returned OK from stream.create()\n");
898 openni::VideoMode options = m_stream.getVideoMode();
899 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl;
900 m_log <<
" " << m_strName << std::endl;
901 m_log <<
" " <<
mrpt::format(
"Initial resolution (%d, %d) FPS %d Format %d", options.getResolutionX(), options.getResolutionY(), options.getFps(), options.getPixelFormat()) << std::endl;
902 if (m_verbose) printf(
"DBG: calling setONI2StreamMode()\n");
903 if(setONI2StreamMode(m_stream,
w, h, fps, m_format) ==
false){
904 m_log <<
" Can't find desired mode in the " << getName() << std::endl;
908 if (m_verbose) printf(
"DBG: returned OK from setONI2StreamMode()\n");
909 if (m_verbose) printf(
"DBG: calling stream.getVideoMode()\n");
910 options = m_stream.getVideoMode();
911 m_log <<
" " <<
mrpt::format(
"-> (%d, %d) FPS %d Format %d", options.getResolutionX(), options.getResolutionY(), options.getFps(), options.getPixelFormat()) << std::endl;
912 if (m_verbose) printf(
" [COpenNI2Generic::CDevice::CStream::open] returning TRUE\n");
917 if(isValid() ==
false){
918 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" " << getName() <<
" is not opened." << std::endl;
921 if(m_stream.start() != openni::STATUS_OK){
922 m_log <<
"[" << __FUNCTION__ <<
"]" << std::endl <<
" Couldn't start " << getName() <<
" stream:" << openni::OpenNI::getExtendedError() << std::endl;
929 COpenNI2Generic::CDevice::CStream::Ptr COpenNI2Generic::CDevice::CStream::create(openni::Device& device,
openni::SensorType type, openni::PixelFormat
format, std::ostream& log,
bool verbose){
930 return Ptr(
new CStream(device,
type,
format, log,verbose));
933 bool COpenNI2Generic::CDevice::CStream::getFrame(openni::VideoFrameRef& frame,
uint64_t ×tamp,
bool &there_is_obs,
bool &hardware_error)
935 there_is_obs =
false;
936 hardware_error =
false;
937 if(isValid() ==
false){
941 if(rc != openni::STATUS_OK){
942 hardware_error =
true;
std::recursive_mutex vDevices_mx
std::vector< std::shared_ptr< COpenNI2Generic::CDevice > > vDevices
std::atomic< int > numInstances(0)
double getHeight(const TPolygon3D &p, const TPoint3D &c)
std::shared_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
static int getNumInstances()
Get the number of OpenNI2 cameras currently open via COpenNI2Generic.
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().
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