23 #ifdef VIDEO_MOD_AVAILABLE
38 mVerbose = verbose_lvl;
43 "ZED Open Capture - Sensors module - Version: "
44 + std::to_string(mMajorVer) +
"."
45 + std::to_string(mMinorVer) +
"."
46 + std::to_string(mPatchVer);
47 INFO_OUT(mVerbose,ver );
56 int SensorCapture::enumerateDevices()
61 struct hid_device_info *devs, *cur_dev;
66 devs = hid_enumerate(SL_USB_VENDOR, 0x0);
69 int fw_major = cur_dev->release_number>>8;
70 int fw_minor = cur_dev->release_number&0x00FF;
71 uint16_t pid = cur_dev->product_id;
72 if(!cur_dev->serial_number)
74 cur_dev = cur_dev->next;
77 std::string sn_str =
wstr2str( cur_dev->serial_number );
78 int sn = std::stoi( sn_str );
81 mSlDevFwVer[sn]=cur_dev->release_number;
85 std::ostringstream smsg;
87 smsg <<
"Device Found: " << std::endl;
88 smsg <<
" VID: " << std::hex << cur_dev->vendor_id <<
" PID: " << std::hex << cur_dev->product_id << std::endl;
89 smsg <<
" Path: " << cur_dev->path << std::endl;
90 smsg <<
" Serial_number: " << sn_str << std::endl;
91 smsg <<
" Manufacturer: " <<
wstr2str(cur_dev->manufacturer_string) << std::endl;
92 smsg <<
" Product: " <<
wstr2str(cur_dev->product_string) << std::endl;
93 smsg <<
" Release number: v" << std::dec << fw_major <<
"." << fw_minor << std::endl;
94 smsg <<
"***" << std::endl;
96 INFO_OUT(mVerbose,smsg.str());
99 cur_dev = cur_dev->next;
102 hid_free_enumeration(devs);
104 return mSlDevPid.size();
109 if(mSlDevPid.size()==0 || refresh)
112 std::vector<int> sn_vec;
114 for(std::map<int,uint16_t>::iterator it = mSlDevPid.begin(); it != mSlDevPid.end(); ++it) {
115 sn_vec.push_back(it->first);
121 bool SensorCapture::open( uint16_t pid,
int serial_number)
123 std::string sn_str = std::to_string(serial_number);
124 std::wstring wide_sn_string = std::wstring(sn_str.begin(), sn_str.end());
126 const wchar_t* wsn = wide_sn_string.c_str();
128 mDevHandle = hid_open(SL_USB_VENDOR, pid, wsn );
130 if(mDevHandle) mDevSerial = serial_number;
132 return mDevHandle!=0;
137 if(mSlDevPid.size()==0)
146 if(mSlDevPid.size()==0)
151 if(mSlDevPid.size()==0)
153 ERROR_OUT(mVerbose,
"No available ZED Mini or ZED2 cameras");
157 sn = mSlDevPid.begin()->first;
160 uint16_t pid = mSlDevPid[sn];
164 std::string msg =
"Connection to device with sn ";
165 msg += std::to_string(sn);
168 ERROR_OUT(mVerbose,msg);
178 std::string msg =
"Connected to device with sn ";
179 msg += std::to_string(sn);
181 INFO_OUT(mVerbose,msg);
184 mDevFwVer = mSlDevFwVer[sn];
186 mInitialized = startCapture();
196 uint16_t release = mSlDevFwVer[mDevSerial];
198 fw_major = release>>8;
199 fw_minor = release&0x00FF;
210 bool SensorCapture::enableDataStream(
bool enable) {
213 unsigned char buf[65];
217 int res = hid_send_feature_report(mDevHandle, buf, 2);
221 std::string msg =
"Unable to set a feature report [SensStreamStatus] - ";
222 msg +=
wstr2str(hid_error(mDevHandle));
224 WARNING_OUT( mVerbose, msg);
233 bool SensorCapture::isDataStreamEnabled() {
238 unsigned char buf[65];
240 int res = hid_get_feature_report(mDevHandle, buf,
sizeof(buf));
243 std::string msg =
"Unable to get a feature report [SensStreamStatus] - ";
244 msg +=
wstr2str(hid_error(mDevHandle));
246 WARNING_OUT( mVerbose,msg );
253 WARNING_OUT(mVerbose,std::string(
"SensStreamStatus size mismatch [REP_ID_SENSOR_STREAM_STATUS]"));
259 WARNING_OUT(mVerbose,std::string(
"SensStreamStatus type mismatch [REP_ID_SENSOR_STREAM_STATUS]") );
264 bool enabled = (buf[1]==1);
269 bool SensorCapture::startCapture()
271 if( !enableDataStream(
true) )
276 mGrabThread = std::thread( &SensorCapture::grabThreadFunc,
this );
281 void SensorCapture::close()
285 if( mGrabThread.joinable() )
290 enableDataStream(
false);
293 hid_close(mDevHandle);
294 mDevHandle =
nullptr;
297 if( mVerbose && mInitialized)
299 std::string msg =
"Device closed";
300 INFO_OUT(mVerbose,msg );
306 void SensorCapture::grabThreadFunc()
308 mStopCapture =
false;
309 mGrabRunning =
false;
314 mNewCamTempData=
false;
317 unsigned char usbBuf[65];
319 int ping_data_count = 0;
321 mFirstImuData =
true;
323 uint64_t rel_mcu_ts = 0;
328 while (!mStopCapture)
333 if(ping_data_count>=400) {
344 int res = hid_read_timeout( mDevHandle, usbBuf, 64, 2000 );
348 hid_set_nonblocking( mDevHandle, 0 );
354 int target_struct_id = 0;
355 if (mDevPid==SL_USB_PROD_MCU_ZED2_REVA || mDevPid==SL_USB_PROD_MCU_ZED2i_REVA)
358 if( usbBuf[0] != target_struct_id)
362 WARNING_OUT(mVerbose,std::string(
"REP_ID_SENSOR_DATA - Sensor Data type mismatch") );
365 hid_set_nonblocking( mDevHandle, 0 );
374 uint64_t mcu_ts_nsec =
static_cast<uint64_t
>(std::round(
static_cast<float>(data->timestamp)*TS_SCALE));
376 if(mFirstImuData && data->imu_not_valid!=1)
381 mLastMcuTs = mcu_ts_nsec;
382 mFirstImuData =
false;
386 uint64_t delta_mcu_ts_raw = mcu_ts_nsec - mLastMcuTs;
390 mLastMcuTs = mcu_ts_nsec;
394 rel_mcu_ts +=
static_cast<uint64_t
>(
static_cast<double>(delta_mcu_ts_raw)*mNTPTsScaling);
397 uint64_t current_data_ts = (mStartSysTs-mSyncOffset) + rel_mcu_ts;
400 if( data->sync_capabilities != 0 )
402 if(mLastFrameSyncCount!=0 && (data->frame_sync!=0 || data->frame_sync_count>mLastFrameSyncCount))
405 std::cout <<
"MCU sync information: " << std::endl;
406 std::cout <<
" * data->frame_sync: " << (int)data->frame_sync << std::endl;
407 std::cout <<
" * data->frame_sync_count: " << data->frame_sync_count << std::endl;
408 std::cout <<
" * mLastFrameSyncCount: " << mLastFrameSyncCount << std::endl;
409 std::cout <<
" * MCU timestamp scaling: " << mNTPTsScaling << std::endl;
412 mMcuTsQueue.push_back( current_data_ts );
419 if (mNTPAdjustedCount <= NTP_ADJUST_CT) {
423 uint64_t first_ts_imu = mMcuTsQueue.at(first_index);
424 uint64_t last_ts_imu = mMcuTsQueue.at(mMcuTsQueue.size()-1);
425 uint64_t first_ts_cam = mSysTsQueue.at(first_index);
426 uint64_t last_ts_cam = mSysTsQueue.at(mSysTsQueue.size()-1);
427 double scale = double(last_ts_cam-first_ts_cam) / double(last_ts_imu-first_ts_imu);
429 if (scale > 1.2) scale = 1.2;
430 if (scale < 0.8) scale = 0.8;
433 mNTPTsScaling*=scale;
442 #ifdef VIDEO_MOD_AVAILABLE
446 mSyncTs = current_data_ts;
454 mLastFrameSyncCount = data->frame_sync_count;
459 mLastIMUData.
sync = data->frame_sync;
461 mLastIMUData.
timestamp = current_data_ts;
462 mLastIMUData.
aX = data->aX*ACC_SCALE;
463 mLastIMUData.
aY = data->aY*ACC_SCALE;
464 mLastIMUData.
aZ = data->aZ*ACC_SCALE;
465 mLastIMUData.
gX = data->gX*GYRO_SCALE;
466 mLastIMUData.
gY = data->gY*GYRO_SCALE;
467 mLastIMUData.
gZ = data->gZ*GYRO_SCALE;
468 mLastIMUData.
temp = data->imu_temp*TEMP_SCALE;
481 mLastMagData.
timestamp = current_data_ts;
482 mLastMagData.
mY = data->mY*MAG_SCALE;
483 mLastMagData.
mZ = data->mZ*MAG_SCALE;
484 mLastMagData.
mX = data->mX*MAG_SCALE;
493 if(data->mag_valid==0)
495 else if(data->mag_valid==1)
507 mLastEnvData.
timestamp = current_data_ts;
508 mLastEnvData.
temp = data->temp*TEMP_SCALE;
511 mLastEnvData.
press = data->press*PRESS_SCALE_NEW;
512 mLastEnvData.
humid = data->humid*HUMID_SCALE_NEW;
516 mLastEnvData.
press = data->press*PRESS_SCALE_OLD;
517 mLastEnvData.
humid = data->humid*HUMID_SCALE_OLD;
527 if(data->env_valid==0)
529 else if(data->env_valid==1)
537 if(data->temp_cam_left != TEMP_NOT_VALID &&
538 data->temp_cam_left != TEMP_NOT_VALID &&
541 mCamTempMutex.lock();
543 mLastCamTempData.
timestamp = current_data_ts;
544 mLastCamTempData.
temp_left = data->temp_cam_left*TEMP_SCALE;
545 mLastCamTempData.
temp_right = data->temp_cam_right*TEMP_SCALE;
546 mNewCamTempData=
true;
547 mCamTempMutex.unlock();
559 mGrabRunning =
false;
562 #ifdef VIDEO_MOD_AVAILABLE
565 static int64_t offset_sum = 0;
566 static int count = 0;
567 offset_sum += (
static_cast<int64_t
>(mSyncTs) -
static_cast<int64_t
>(frame_ts));
572 int64_t offset = offset_sum/count;
573 mSyncOffset += offset;
575 std::cout <<
"Offset: " << offset << std::endl;
576 std::cout <<
"mSyncOffset: " << mSyncOffset << std::endl;
585 bool SensorCapture::sendPing() {
589 unsigned char buf[65];
593 int res = hid_send_feature_report(mDevHandle, buf, 2);
596 std::string msg =
"Unable to send ping [REP_ID_REQUEST_SET-RQ_CMD_PING] - ";
597 msg +=
wstr2str(hid_error(mDevHandle));
599 WARNING_OUT(mVerbose,msg);
607 bool SensorCapture::searchForConnectedDev(
int* serial_number,
unsigned short* found_pid)
609 int in_serial_number;
610 if(serial_number==
nullptr)
611 in_serial_number = 0;
613 in_serial_number = *serial_number;
614 int found_serial_number = 0;
617 struct hid_device_info *devs, *cur_dev;
622 devs = hid_enumerate(SL_USB_VENDOR, 0x0);
632 pid = cur_dev->product_id;
633 sn_str =
wstr2str( cur_dev->serial_number );
634 int sn = std::stoi( sn_str );
636 if(in_serial_number==0 || sn==in_serial_number)
638 if( pid==SL_USB_PROD_MCU_ZED2_REVA || pid==SL_USB_PROD_MCU_ZED2i_REVA)
641 found_serial_number = sn;
646 std::string msg =
"The reset function works only for ZED2/ZED2i camera models.";
647 std::cerr << msg << std::endl;
649 if(in_serial_number==0)
656 cur_dev = cur_dev->next;
659 hid_free_enumeration(devs);
667 *serial_number = found_serial_number;
675 int found_sn = serial_number;
677 bool res = searchForConnectedDev(&found_sn, &pid);
683 msg =
"[sl_oc::sensors::SensorCapture] WARNING: Sensors Module reset failed. Unable to find the Sensor Module with serial number ";
684 msg += std::to_string(serial_number);
688 msg =
"[sl_oc::sensors::SensorCapture] WARNING: Sensors Module reset failed. Unable to find the Sensor Module of a ZED2 camera. Please verify the USB connection.";
691 std::cerr << msg << std::endl;
696 std::string sn_str = std::to_string(found_sn);
697 std::wstring wide_sn_string = std::wstring(sn_str.begin(), sn_str.end());
698 const wchar_t* wsn = wide_sn_string.c_str();
700 hid_device* devHandle = hid_open(SL_USB_VENDOR, pid, wsn );
704 std::string msg =
"Unable to open the MCU HID device";
705 std::cerr << msg << std::endl;
710 unsigned char buf[65];
714 hid_send_feature_report(devHandle, buf, 2);
720 std::cerr <<
"[sl_oc::sensors::SensorCapture] INFO: Sensors Module reset successful" << std::endl;
727 int found_sn = serial_number;
729 bool res = searchForConnectedDev(&found_sn, &pid);
735 msg =
"[sl_oc::sensors::SensorCapture] WARNING: Video Module reset failed. Unable to find the Sensor Module with serial number ";
736 msg += std::to_string(serial_number);
740 msg =
"[sl_oc::sensors::SensorCapture] WARNING: Video Module reset failed. Unable to find the Sensor Module of a ZED2 camera. Please verify the USB connection.";
743 std::cerr << msg << std::endl;
748 std::string sn_str = std::to_string(found_sn);
749 std::wstring wide_sn_string = std::wstring(sn_str.begin(), sn_str.end());
750 const wchar_t* wsn = wide_sn_string.c_str();
752 hid_device* devHandle = hid_open(SL_USB_VENDOR, pid, wsn );
756 std::string msg =
"Unable to open the MCU HID device";
757 std::cerr << msg << std::endl;
767 unsigned char buf[65];
771 hid_close(devHandle);
774 std::cerr <<
"[sl_oc::sensors::SensorCapture] INFO: Video Module reset failed" << std::endl;
780 std::cerr <<
"[sl_oc::sensors::SensorCapture] INFO: Video Module reset successful" << std::endl;
787 uint64_t time_count = (timeout_usec<100?100:timeout_usec)/100;
788 while( !mNewIMUData )
802 const std::lock_guard<std::mutex> lock(mIMUMutex);
810 uint64_t time_count = (timeout_usec<100?100:timeout_usec)/10;
811 while( !mNewMagData )
825 const std::lock_guard<std::mutex> lock(mMagMutex);
833 uint64_t time_count = (timeout_usec<100?100:timeout_usec)/10;
834 while( !mNewEnvData )
848 const std::lock_guard<std::mutex> lock(mEnvMutex);
856 uint64_t time_count = (timeout_usec<100?100:timeout_usec)/10;
857 while( !mNewCamTempData )
863 return mLastCamTempData;
871 const std::lock_guard<std::mutex> lock(mCamTempMutex);
872 mNewCamTempData =
false;
873 return mLastCamTempData;
int getSerialNumber()
Retrieve the serial number of the connected camera.
void updateTimestampOffset(uint64_t frame_ts)
Called by VideoCapture to update timestamp offset.
std::vector< int > getDeviceList(bool refresh=false)
Get the list of the serial number of all the available devices.
bool initializeSensors(int sn=-1)
Open a connection to the MCU of a ZED Mini or a ZED2 camera using the specified serial number or sear...
virtual ~SensorCapture()
The class destructor.
void getFirmwareVersion(uint16_t &fw_major, uint16_t &fw_minor)
Get the MCU firmware version in form [fw_major].[fw_minor].
const data::Imu & getLastIMUData(uint64_t timeout_usec=1500)
Get the last received IMU data.
static bool resetVideoModule(int serial_number=0)
Perform a reset of the video module without resetting the sensor module. To be called in case the Vid...
const data::Magnetometer & getLastMagnetometerData(uint64_t timeout_usec=100)
Get the last received Magnetometer data.
const data::Temperature & getLastCameraTemperatureData(uint64_t timeout_usec=100)
Get the last received camera sensors temperature data.
static bool resetSensorModule(int serial_number=0)
Perform a SW reset of the Sensors Module. To be called in case one of the sensors stops to work corre...
const data::Environment & getLastEnvironmentData(uint64_t timeout_usec=100)
Get the last received Environment data.
SensorCapture(sl_oc::VERBOSITY verbose_lvl=sl_oc::VERBOSITY::ERROR)
The default constructor.
void setReadyToSync()
Indicates that the SensorCapture object received the HW sync signal and a frame must be synchronized ...
uint64_t getSteadyTimestamp()
Get the current system clock as steady clock, so with no jumps even if the system time changes.
uint64_t getWallTimestamp()
Get the current system clock as wall clock (it can have jumps if the system clock is updated by a syn...
@ RQ_CMD_PING
Command to ping the MCU to communicate that host is alive.
@ OV580_CMD_RESET
Command to reset the OV580 using the MCU.
@ RQ_CMD_RST
Command to reset the MCU.
@ REP_ID_SENSOR_STREAM_STATUS
Stream Status report ID.
@ REP_ID_OV580_CMD
OV580 control request.
@ REP_ID_REQUEST_SET
USB Request report ID.
@ REP_ID_SENSOR_DATA
Sensor data report ID.
struct sl_oc::sensors::usb::StreamStatus StreamStatus
Status of the usb data streaming.
struct sl_oc::sensors::usb::RawData RawData
The RAW sensor data structure retrieved from camera MCU by USB.
const size_t TS_SHIFT_VAL_COUNT
Number of sensor data to use to update timestamp scaling.
bool atLeast(const int &version_current, const ZED_2_FW &version_required)
Check firmware version for ZED2 camera.
std::string wstr2str(const wchar_t *wstr)
Convert a wchar array to std::string.
Contains the acquired Environment data.
float press
Atmospheric pressure in hPa.
float temp
Sensor temperature in °C.
EnvStatus valid
Indicates if Environmental data are valid.
float humid
Humidity in rH.
uint64_t timestamp
Timestamp in nanoseconds.
Contains the acquired Imu data.
float gX
Angular velocity around X axis in °/s.
float aX
Acceleration along X axis in m/s²
ImuStatus valid
Indicates if IMU data are valid.
uint64_t timestamp
Timestamp in nanoseconds.
bool sync
Indicates in IMU data are synchronized with a video frame.
float temp
Sensor temperature in °C.
float gZ
Angular velocity around > axis in °/s.
float gY
Angular velocity around Y axis in °/s.
float aY
Acceleration along Y axis in m/s²
float aZ
Acceleration along Z axis in m/s²
Contains the acquired Magnetometer data.
float mY
Acceleration along Y axis in uT.
float mX
Acceleration along X axis in uT.
MagStatus valid
Indicates if Magnetometer data are valid.
uint64_t timestamp
Timestamp in nanoseconds.
float mZ
Acceleration along Z axis in uT.
Contains the acquired Camera Temperature data.
float temp_right
Temperature of the right CMOS camera sensor.
uint64_t timestamp
Timestamp in nanoseconds.
float temp_left
Temperature of the left CMOS camera sensor.
TempStatus valid
Indicates if camera temperature data are valid.
OV580 control using the MCU.
uint8_t cmd
command to be sent to OV580: OV580_RESET
uint8_t struct_id
struct identifier for HID comm