ZED Open Capture  v0.6.0
Low level camera driver for the ZED stereo camera family
sensorcapture.cpp
Go to the documentation of this file.
1 //
3 // Copyright (c) 2021, STEREOLABS.
4 //
5 // All rights reserved.
6 //
7 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
8 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
9 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
10 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
11 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
12 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
13 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
14 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
15 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
16 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
17 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
18 //
20 
21 #include "sensorcapture.hpp"
22 
23 #ifdef VIDEO_MOD_AVAILABLE
24 
25 #include "videocapture.hpp"
26 #endif
27 
28 #include <sstream>
29 #include <cmath> // for round
30 #include <unistd.h> // for usleep, close
31 
32 namespace sl_oc {
33 
34 namespace sensors {
35 
37 {
38  mVerbose = verbose_lvl;
39 
40  if( mVerbose )
41  {
42  std::string ver =
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 );
48  }
49 }
50 
52 {
53  close();
54 }
55 
56 int SensorCapture::enumerateDevices()
57 {
58  mSlDevPid.clear();
59  mSlDevFwVer.clear();
60 
61  struct hid_device_info *devs, *cur_dev;
62 
63  if (hid_init()==-1)
64  return 0;
65 
66  devs = hid_enumerate(SL_USB_VENDOR, 0x0);
67  cur_dev = devs;
68  while (cur_dev) {
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)
73  {
74  cur_dev = cur_dev->next;
75  continue;
76  }
77  std::string sn_str = wstr2str( cur_dev->serial_number );
78  int sn = std::stoi( sn_str );
79 
80  mSlDevPid[sn]=pid;
81  mSlDevFwVer[sn]=cur_dev->release_number;
82 
83  if(mVerbose)
84  {
85  std::ostringstream smsg;
86 
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;
95 
96  INFO_OUT(mVerbose,smsg.str());
97  }
98 
99  cur_dev = cur_dev->next;
100  }
101 
102  hid_free_enumeration(devs);
103 
104  return mSlDevPid.size();
105 }
106 
107 std::vector<int> SensorCapture::getDeviceList(bool refresh)
108 {
109  if(mSlDevPid.size()==0 || refresh)
110  enumerateDevices();
111 
112  std::vector<int> sn_vec;
113 
114  for(std::map<int,uint16_t>::iterator it = mSlDevPid.begin(); it != mSlDevPid.end(); ++it) {
115  sn_vec.push_back(it->first);
116  }
117 
118  return sn_vec;
119 }
120 
121 bool SensorCapture::open( uint16_t pid, int serial_number)
122 {
123  std::string sn_str = std::to_string(serial_number);
124  std::wstring wide_sn_string = std::wstring(sn_str.begin(), sn_str.end());
125 
126  const wchar_t* wsn = wide_sn_string.c_str();
127 
128  mDevHandle = hid_open(SL_USB_VENDOR, pid, wsn );
129 
130  if(mDevHandle) mDevSerial = serial_number;
131 
132  return mDevHandle!=0;
133 }
134 
136 {
137  if(mSlDevPid.size()==0)
138  {
139  enumerateDevices();
140  }
141 
142  std::string sn_str;
143 
144  if(sn==-1)
145  {
146  if(mSlDevPid.size()==0)
147  {
148  enumerateDevices();
149  }
150 
151  if(mSlDevPid.size()==0)
152  {
153  ERROR_OUT(mVerbose,"No available ZED Mini or ZED2 cameras");
154  return false;
155  }
156 
157  sn = mSlDevPid.begin()->first;
158  }
159 
160  uint16_t pid = mSlDevPid[sn];
161 
162  if(!open( pid,sn))
163  {
164  std::string msg = "Connection to device with sn ";
165  msg += std::to_string(sn);
166  msg += " failed";
167 
168  ERROR_OUT(mVerbose,msg);
169 
170  mDevFwVer = -1;
171  mDevSerial = -1;
172 
173  return false;
174  }
175 
176  if(mVerbose)
177  {
178  std::string msg = "Connected to device with sn ";
179  msg += std::to_string(sn);
180 
181  INFO_OUT(mVerbose,msg);
182  }
183 
184  mDevFwVer = mSlDevFwVer[sn];
185  mDevPid = pid;
186  mInitialized = startCapture();
187 
188  return true;
189 }
190 
191 void SensorCapture::getFirmwareVersion( uint16_t& fw_major, uint16_t& fw_minor )
192 {
193  if(mDevSerial==-1)
194  return;
195 
196  uint16_t release = mSlDevFwVer[mDevSerial];
197 
198  fw_major = release>>8;
199  fw_minor = release&0x00FF;
200 }
201 
203 {
204  if(mDevSerial==-1)
205  return -1;
206 
207  return mDevSerial;
208 }
209 
210 bool SensorCapture::enableDataStream(bool enable) {
211  if( !mDevHandle )
212  return false;
213  unsigned char buf[65];
215  buf[1] = enable?1:0;
216 
217  int res = hid_send_feature_report(mDevHandle, buf, 2);
218  if (res < 0) {
219  if(mVerbose)
220  {
221  std::string msg = "Unable to set a feature report [SensStreamStatus] - ";
222  msg += wstr2str(hid_error(mDevHandle));
223 
224  WARNING_OUT( mVerbose, msg);
225  }
226 
227  return false;
228  }
229 
230  return true;
231 }
232 
233 bool SensorCapture::isDataStreamEnabled() {
234  if( !mDevHandle ) {
235  return false;
236  }
237 
238  unsigned char buf[65];
240  int res = hid_get_feature_report(mDevHandle, buf, sizeof(buf));
241  if (res < 0)
242  {
243  std::string msg = "Unable to get a feature report [SensStreamStatus] - ";
244  msg += wstr2str(hid_error(mDevHandle));
245 
246  WARNING_OUT( mVerbose,msg );
247 
248  return false;
249  }
250 
251  if( res < static_cast<int>(sizeof(usb::StreamStatus)) )
252  {
253  WARNING_OUT(mVerbose,std::string("SensStreamStatus size mismatch [REP_ID_SENSOR_STREAM_STATUS]"));
254  return false;
255  }
256 
257  if( buf[0] != usb::REP_ID_SENSOR_STREAM_STATUS )
258  {
259  WARNING_OUT(mVerbose,std::string("SensStreamStatus type mismatch [REP_ID_SENSOR_STREAM_STATUS]") );
260 
261  return false;
262  }
263 
264  bool enabled = (buf[1]==1);
265 
266  return enabled;
267 }
268 
269 bool SensorCapture::startCapture()
270 {
271  if( !enableDataStream(true) )
272  {
273  return false;
274  }
275 
276  mGrabThread = std::thread( &SensorCapture::grabThreadFunc,this );
277 
278  return true;
279 }
280 
281 void SensorCapture::close()
282 {
283  mStopCapture = true;
284 
285  if( mGrabThread.joinable() )
286  {
287  mGrabThread.join();
288  }
289 
290  enableDataStream(false);
291 
292  if( mDevHandle ) {
293  hid_close(mDevHandle);
294  mDevHandle = nullptr;
295  }
296 
297  if( mVerbose && mInitialized)
298  {
299  std::string msg = "Device closed";
300  INFO_OUT(mVerbose,msg );
301  }
302 
303  mInitialized=false;
304 }
305 
306 void SensorCapture::grabThreadFunc()
307 {
308  mStopCapture = false;
309  mGrabRunning = false;
310 
311  mNewIMUData=false;
312  mNewMagData=false;
313  mNewEnvData=false;
314  mNewCamTempData=false;
315 
316  // Read sensor data
317  unsigned char usbBuf[65];
318 
319  int ping_data_count = 0;
320 
321  mFirstImuData = true;
322 
323  uint64_t rel_mcu_ts = 0;
324 
325  mSysTsQueue.reserve(TS_SHIFT_VAL_COUNT);
326  mMcuTsQueue.reserve(TS_SHIFT_VAL_COUNT);
327 
328  while (!mStopCapture)
329  {
330  // ----> Keep data stream alive
331  // sending a ping aboutonce per second
332  // to keep the streaming alive
333  if(ping_data_count>=400) {
334  ping_data_count=0;
335  sendPing();
336  };
337  ping_data_count++;
338  // <---- Keep data stream alive
339 
340  mGrabRunning=true;
341 
342  // Sensor data request
343  usbBuf[1]=usb::REP_ID_SENSOR_DATA;
344  int res = hid_read_timeout( mDevHandle, usbBuf, 64, 2000 );
345 
346  // ----> Data received?
347  if( res < static_cast<int>(sizeof(usb::RawData)) ) {
348  hid_set_nonblocking( mDevHandle, 0 );
349  continue;
350  }
351  // <---- Data received?
352 
353  // ----> Received data are correct?
354  int target_struct_id = 0;
355  if (mDevPid==SL_USB_PROD_MCU_ZED2_REVA || mDevPid==SL_USB_PROD_MCU_ZED2i_REVA)
356  target_struct_id = usb::REP_ID_SENSOR_DATA;
357 
358  if( usbBuf[0] != target_struct_id)
359  {
360  if(mVerbose)
361  {
362  WARNING_OUT(mVerbose,std::string("REP_ID_SENSOR_DATA - Sensor Data type mismatch") );
363  }
364 
365  hid_set_nonblocking( mDevHandle, 0 );
366  continue;
367  }
368  // <---- Received data are correct?
369 
370  // Data structure static conversion
371  usb::RawData* data = (usb::RawData*)usbBuf;
372 
373  // ----> Timestamp update
374  uint64_t mcu_ts_nsec = static_cast<uint64_t>(std::round(static_cast<float>(data->timestamp)*TS_SCALE));
375 
376  if(mFirstImuData && data->imu_not_valid!=1)
377  {
378  mStartSysTs = getWallTimestamp(); // Starting system timestamp
379  //std::cout << "SensorCapture: " << mStartSysTs << std::endl;
380 
381  mLastMcuTs = mcu_ts_nsec;
382  mFirstImuData = false;
383  continue;
384  }
385 
386  uint64_t delta_mcu_ts_raw = mcu_ts_nsec - mLastMcuTs;
387 
388  //std::cout << "Internal MCU freq: " << 1e9/delta_mcu_ts_raw << " Hz" << std::endl;
389 
390  mLastMcuTs = mcu_ts_nsec;
391  // <---- Timestamp update
392 
393  // Apply timestamp drift scaling factor
394  rel_mcu_ts += static_cast<uint64_t>(static_cast<double>(delta_mcu_ts_raw)*mNTPTsScaling);
395 
396  // mStartSysTs is synchronized to Video TS when sync is enabled using \ref VideoCapture::enableSensorSync
397  uint64_t current_data_ts = (mStartSysTs-mSyncOffset) + rel_mcu_ts;
398 
399  // ----> Camera/Sensors Synchronization
400  if( data->sync_capabilities != 0 ) // Synchronization active
401  {
402  if(mLastFrameSyncCount!=0 && (data->frame_sync!=0 || data->frame_sync_count>mLastFrameSyncCount))
403  {
404 #if 0 // Timestamp sync debug info
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;
410 #endif
411  mSysTsQueue.push_back( getSteadyTimestamp() ); // Steady host timestamp
412  mMcuTsQueue.push_back( current_data_ts ); // MCU timestamp
413 
414  // Once we have enough data, calculate the drift scaling factor
415  if (mSysTsQueue.size()==TS_SHIFT_VAL_COUNT && mMcuTsQueue.size() == TS_SHIFT_VAL_COUNT)
416  {
417  //First and last ts
418  int first_index = 5;
419  if (mNTPAdjustedCount <= NTP_ADJUST_CT) {
420  first_index = TS_SHIFT_VAL_COUNT/2;
421  }
422 
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);
428  //CLAMP
429  if (scale > 1.2) scale = 1.2;
430  if (scale < 0.8) scale = 0.8;
431 
432  //Adjust scaling continuoulsy. No jump so that ts(n) - ts(n-1) == 400Hz
433  mNTPTsScaling*=scale;
434 
435  //scale will be applied to the next values, so clear the vector and wait until we have enough data again
436  mMcuTsQueue.clear();
437  mSysTsQueue.clear();
438 
439  // Count the number of completed time shift factor estimations
440  mNTPAdjustedCount++;
441 
442 #ifdef VIDEO_MOD_AVAILABLE
443  // ----> Signal update offset to VideoCapture
444  if(mVideoPtr)
445  {
446  mSyncTs = current_data_ts;
447  mVideoPtr->setReadyToSync();
448  }
449  // <---- Update offset
450 #endif //VIDEO_MOD_AVAILABLE
451  }
452  }
453  }
454  mLastFrameSyncCount = data->frame_sync_count;
455  // <---- Camera/Sensors Synchronization
456 
457  // ----> IMU data
458  mIMUMutex.lock();
459  mLastIMUData.sync = data->frame_sync;
460  mLastIMUData.valid = (data->imu_not_valid!=1)?(data::Imu::NEW_VAL):(data::Imu::OLD_VAL);
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;
469  mNewIMUData = true;
470  mIMUMutex.unlock();
471 
472  //std::string msg = std::to_string(mLastMAGData.timestamp);
473  //INFO_OUT(msg);
474  // <---- IMU data
475 
476  // ----> Magnetometer data
477  if(data->mag_valid == data::Magnetometer::NEW_VAL)
478  {
479  mMagMutex.lock();
480  mLastMagData.valid = data::Magnetometer::NEW_VAL;
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;
485  mNewMagData = true;
486  mMagMutex.unlock();
487 
488  //std::string msg = std::to_string(mLastMAGData.timestamp);
489  //INFO_OUT(msg);
490  }
491  else
492  {
493  if(data->mag_valid==0)
494  mLastMagData.valid = data::Magnetometer::NOT_PRESENT;
495  else if(data->mag_valid==1)
496  mLastMagData.valid = data::Magnetometer::OLD_VAL;
497  else
498  mLastMagData.valid = data::Magnetometer::NEW_VAL;
499  }
500  // <---- Magnetometer data
501 
502  // ----> Environmental data
503  if(data->env_valid == data::Environment::NEW_VAL)
504  {
505  mEnvMutex.lock();
506  mLastEnvData.valid = data::Environment::NEW_VAL;
507  mLastEnvData.timestamp = current_data_ts;
508  mLastEnvData.temp = data->temp*TEMP_SCALE;
509  if( atLeast(mDevFwVer, ZED_2_FW::FW_3_9))
510  {
511  mLastEnvData.press = data->press*PRESS_SCALE_NEW;
512  mLastEnvData.humid = data->humid*HUMID_SCALE_NEW;
513  }
514  else
515  {
516  mLastEnvData.press = data->press*PRESS_SCALE_OLD;
517  mLastEnvData.humid = data->humid*HUMID_SCALE_OLD;
518  }
519  mNewEnvData = true;
520  mEnvMutex.unlock();
521 
522  //std::string msg = std::to_string(mLastENVData.timestamp);
523  //INFO_OUT(msg);
524  }
525  else
526  {
527  if(data->env_valid==0)
528  mLastEnvData.valid = data::Environment::NOT_PRESENT;
529  else if(data->env_valid==1)
530  mLastEnvData.valid = data::Environment::OLD_VAL;
531  else
532  mLastEnvData.valid = data::Environment::NEW_VAL;
533  }
534  // <---- Environmental data
535 
536  // ----> Camera sensors temperature data
537  if(data->temp_cam_left != TEMP_NOT_VALID &&
538  data->temp_cam_left != TEMP_NOT_VALID &&
539  data->env_valid == data::Environment::NEW_VAL ) // Sensor temperature is linked to Environmental data acquisition at FW level
540  {
541  mCamTempMutex.lock();
542  mLastCamTempData.valid = data::Temperature::NEW_VAL;
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();
548 
549  //std::string msg = std::to_string(mLastCamTempData.timestamp);
550  //INFO_OUT(msg);
551  }
552  else
553  {
554  mLastCamTempData.valid = data::Temperature::OLD_VAL;
555  }
556  // <---- Camera sensors temperature data
557  }
558 
559  mGrabRunning = false;
560 }
561 
562 #ifdef VIDEO_MOD_AVAILABLE
563 void SensorCapture::updateTimestampOffset( uint64_t frame_ts)
564 {
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));
568  count++;
569 
570  if(count==3)
571  {
572  int64_t offset = offset_sum/count;
573  mSyncOffset += offset;
574 #if 0
575  std::cout << "Offset: " << offset << std::endl;
576  std::cout << "mSyncOffset: " << mSyncOffset << std::endl;
577 #endif
578 
579  offset_sum = 0;
580  count=0;
581  }
582 }
583 #endif
584 
585 bool SensorCapture::sendPing() {
586  if( !mDevHandle )
587  return false;
588 
589  unsigned char buf[65];
590  buf[0] = usb::REP_ID_REQUEST_SET;
591  buf[1] = usb::RQ_CMD_PING;
592 
593  int res = hid_send_feature_report(mDevHandle, buf, 2);
594  if (res < 0)
595  {
596  std::string msg = "Unable to send ping [REP_ID_REQUEST_SET-RQ_CMD_PING] - ";
597  msg += wstr2str(hid_error(mDevHandle));
598 
599  WARNING_OUT(mVerbose,msg);
600 
601  return false;
602  }
603 
604  return true;
605 }
606 
607 bool SensorCapture::searchForConnectedDev(int* serial_number, unsigned short* found_pid)
608 {
609  int in_serial_number;
610  if(serial_number==nullptr)
611  in_serial_number = 0;
612  else
613  in_serial_number = *serial_number;
614  int found_serial_number = 0;
615 
616  // ----> Search for connected device
617  struct hid_device_info *devs, *cur_dev;
618 
619  if (hid_init()==-1)
620  return false;
621 
622  devs = hid_enumerate(SL_USB_VENDOR, 0x0);
623  cur_dev = devs;
624 
625  bool found = false;
626  uint16_t pid=0;
627  std::string sn_str;
628 
629  while (cur_dev) {
630  //int fw_major = cur_dev->release_number>>8;
631  //int fw_minor = cur_dev->release_number&0x00FF;
632  pid = cur_dev->product_id;
633  sn_str = wstr2str( cur_dev->serial_number );
634  int sn = std::stoi( sn_str );
635 
636  if(in_serial_number==0 || sn==in_serial_number)
637  {
638  if( pid==SL_USB_PROD_MCU_ZED2_REVA || pid==SL_USB_PROD_MCU_ZED2i_REVA)
639  {
640  found = true;
641  found_serial_number = sn;
642  break;
643  }
644  else
645  {
646  std::string msg = "The reset function works only for ZED2/ZED2i camera models.";
647  std::cerr << msg << std::endl;
648 
649  if(in_serial_number==0)
650  continue;
651  else
652  return false;
653  }
654  }
655 
656  cur_dev = cur_dev->next;
657  }
658 
659  hid_free_enumeration(devs);
660  // <---- Search for connected device
661 
662  if(!found) {
663  return false;
664  }
665 
666  if(serial_number)
667  *serial_number = found_serial_number;
668  if(found_pid)
669  *found_pid = pid;
670  return true;
671 }
672 
673 bool SensorCapture::resetSensorModule(int serial_number)
674 {
675  int found_sn = serial_number;
676  unsigned short pid;
677  bool res = searchForConnectedDev(&found_sn, &pid);
678  if(!res)
679  {
680  std::string msg;
681  if(serial_number!=0)
682  {
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);
685  }
686  else
687  {
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.";
689  }
690 
691  std::cerr << msg << std::endl;
692 
693  return false;
694  }
695 
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();
699 
700  hid_device* devHandle = hid_open(SL_USB_VENDOR, pid, wsn );
701 
702  if(!devHandle)
703  {
704  std::string msg = "Unable to open the MCU HID device";
705  std::cerr << msg << std::endl;
706 
707  return false;
708  }
709 
710  unsigned char buf[65];
711  buf[0] = static_cast<unsigned char>(usb::REP_ID_REQUEST_SET);
712  buf[1] = static_cast<unsigned char>(usb::RQ_CMD_RST);
713 
714  hid_send_feature_report(devHandle, buf, 2);
715  // Note: cannot verify the return value of the `hid_send_feature_report` command because the MCU is suddenly reset
716  // and it cannot return a valid value
717 
718  sleep(2); // Wait for MCU and OV580 to reboot
719 
720  std::cerr << "[sl_oc::sensors::SensorCapture] INFO: Sensors Module reset successful" << std::endl;
721 
722  return true;
723 }
724 
725 bool SensorCapture::resetVideoModule(int serial_number)
726 {
727  int found_sn = serial_number;
728  unsigned short pid;
729  bool res = searchForConnectedDev(&found_sn, &pid);
730  if(!res)
731  {
732  std::string msg;
733  if(serial_number!=0)
734  {
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);
737  }
738  else
739  {
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.";
741  }
742 
743  std::cerr << msg << std::endl;
744 
745  return false;
746  }
747 
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();
751 
752  hid_device* devHandle = hid_open(SL_USB_VENDOR, pid, wsn );
753 
754  if(!devHandle)
755  {
756  std::string msg = "Unable to open the MCU HID device";
757  std::cerr << msg << std::endl;
758 
759  return false;
760  }
761 
765  cmd.info=0;
766 
767  unsigned char buf[65];
768  memcpy(buf, &(cmd.struct_id), sizeof(usb::OV580CmdStruct));
769 
770  int ret = hid_send_feature_report(devHandle, buf, sizeof(usb::OV580CmdStruct));
771  hid_close(devHandle);
772 
773  if(ret!=sizeof(usb::OV580CmdStruct)) {
774  std::cerr << "[sl_oc::sensors::SensorCapture] INFO: Video Module reset failed" << std::endl;
775  return false;
776  }
777 
778  sleep(2); // Wait for OV580 to reboot
779 
780  std::cerr << "[sl_oc::sensors::SensorCapture] INFO: Video Module reset successful" << std::endl;
781  return true;
782 }
783 
784 const data::Imu& SensorCapture::getLastIMUData(uint64_t timeout_usec)
785 {
786  // ----> Wait for a new frame
787  uint64_t time_count = (timeout_usec<100?100:timeout_usec)/100;
788  while( !mNewIMUData )
789  {
790  if(time_count==0)
791  {
792  if(mLastIMUData.valid!=data::Imu::NOT_PRESENT)
793  mLastIMUData.valid = data::Imu::OLD_VAL;
794  return mLastIMUData;
795  }
796  time_count--;
797  usleep(100);
798  }
799  // <---- Wait for a new frame
800 
801  // Get the frame mutex
802  const std::lock_guard<std::mutex> lock(mIMUMutex);
803  mNewIMUData = false;
804  return mLastIMUData;
805 }
806 
808 {
809  // ----> Wait for a new frame
810  uint64_t time_count = (timeout_usec<100?100:timeout_usec)/10;
811  while( !mNewMagData )
812  {
813  if(time_count==0)
814  {
815  if(mLastMagData.valid!=data::Magnetometer::NOT_PRESENT)
816  mLastMagData.valid=data::Magnetometer::OLD_VAL;
817  return mLastMagData;
818  }
819  time_count--;
820  usleep(10);
821  }
822  // <---- Wait for a new frame
823 
824  // Get the frame mutex
825  const std::lock_guard<std::mutex> lock(mMagMutex);
826  mNewMagData = false;
827  return mLastMagData;
828 }
829 
831 {
832  // ----> Wait for a new frame
833  uint64_t time_count = (timeout_usec<100?100:timeout_usec)/10;
834  while( !mNewEnvData )
835  {
836  if(time_count==0)
837  {
838  if(mLastEnvData.valid!=data::Environment::NOT_PRESENT)
839  mLastEnvData.valid = data::Environment::OLD_VAL;
840  return mLastEnvData;
841  }
842  time_count--;
843  usleep(10);
844  }
845  // <---- Wait for a new frame
846 
847  // Get the frame mutex
848  const std::lock_guard<std::mutex> lock(mEnvMutex);
849  mNewEnvData = false;
850  return mLastEnvData;
851 }
852 
854 {
855  // ----> Wait for a new frame
856  uint64_t time_count = (timeout_usec<100?100:timeout_usec)/10;
857  while( !mNewCamTempData )
858  {
859  if(time_count==0)
860  {
861  if(mLastCamTempData.valid!=data::Temperature::NOT_PRESENT)
862  mLastCamTempData.valid = data::Temperature::OLD_VAL;
863  return mLastCamTempData;
864  }
865  time_count--;
866  usleep(10);
867  }
868  // <---- Wait for a new frame
869 
870  // Get the frame mutex
871  const std::lock_guard<std::mutex> lock(mCamTempMutex);
872  mNewCamTempData = false;
873  return mLastCamTempData;
874 }
875 
876 }
877 
878 }
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.
Definition: defines.hpp:63
uint64_t getWallTimestamp()
Get the current system clock as wall clock (it can have jumps if the system clock is updated by a syn...
Definition: defines.hpp:69
@ 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.
VERBOSITY
Definition: defines.hpp:85
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.
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.
uint8_t cmd
command to be sent to OV580: OV580_RESET
uint8_t struct_id
struct identifier for HID comm