YARP
Yet Another Robot Platform
realsense2Tracking.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
3  * All rights reserved.
4  *
5  * This software may be modified and distributed under the terms of the
6  * BSD-3-Clause license. See the accompanying LICENSE file for details.
7  */
8 
9 #include "realsense2Tracking.h"
10 
11 #include <yarp/os/LogComponent.h>
12 #include <yarp/os/Value.h>
13 
14 #include <yarp/sig/ImageUtils.h>
15 
16 #include <yarp/math/Quaternion.h>
17 #include <yarp/math/Math.h>
18 
19 #include <algorithm>
20 #include <cmath>
21 #include <cstdint>
22 #include <iomanip>
23 #include <librealsense2/rsutil.h>
24 #include <librealsense2/rs.hpp>
25 #include <mutex>
26 
27  /**********************************************************************************************************/
28  // This software module is experimental.
29  // It is provided with uncomplete documentation and it may be modified/renamed/removed without any notice.
30  /**********************************************************************************************************/
31 
32 using namespace yarp::dev;
33 using namespace yarp::sig;
34 using namespace yarp::os;
35 
36 using namespace std;
37 
38 namespace {
39 YARP_LOG_COMPONENT(REALSENSE2TRACKING, "yarp.device.realsense2Tracking")
40 }
41 
42 
43 struct float3 {
44  float x;
45  float y;
46  float z;
47 
49  {
50  return { x * t, y * t, z * t };
51  }
52 
54  {
55  return { x - t, y - t, z - t };
56  }
57 
58  void operator*=(float t)
59  {
60  x = x * t;
61  y = y * t;
62  z = z * t;
63  }
64 
65  void add(float t1, float t2, float t3)
66  {
67  x += t1;
68  y += t2;
69  z += t3;
70  }
71 };
72 
73 //---------------------------------------------------------------
74 
75 #if 0
76 static std::string get_device_information(const rs2::device& dev)
77 {
78 
79  std::stringstream ss;
80  ss << "Device information: " << std::endl;
81 
82  for (int i = 0; i < static_cast<int>(RS2_CAMERA_INFO_COUNT); i++) {
83  auto info_type = static_cast<rs2_camera_info>(i);
84  ss << " " << std::left << std::setw(20) << info_type << " : ";
85 
86  if (dev.supports(info_type))
87  ss << dev.get_info(info_type) << std::endl;
88  else
89  ss << "N/A" << std::endl;
90  }
91  return ss.str();
92 }
93 
94 static bool setOption(rs2_option option, const rs2::sensor* sensor, float value)
95 {
96 
97  if (!sensor) {
98  return false;
99  }
100 
101  // First, verify that the sensor actually supports this option
102  if (!sensor->supports(option)) {
103  yCError(REALSENSE2TRACKING) << "The option" << rs2_option_to_string(option) << "is not supported by this sensor";
104  return false;
105  }
106 
107  // To set an option to a different value, we can call set_option with a new value
108  try {
109  sensor->set_option(option, value);
110  } catch (const rs2::error& e) {
111  // Some options can only be set while the camera is streaming,
112  // and generally the hardware might fail so it is good practice to catch exceptions from set_option
113  yCError(REALSENSE2TRACKING) << "Failed to set option " << rs2_option_to_string(option) << ". (" << e.what() << ")";
114  return false;
115  }
116  return true;
117 }
118 
119 static bool getOption(rs2_option option, const rs2::sensor* sensor, float& value)
120 {
121  if (!sensor) {
122  return false;
123  }
124 
125  // First, verify that the sensor actually supports this option
126  if (!sensor->supports(option)) {
127  yCError(REALSENSE2TRACKING) << "The option" << rs2_option_to_string(option) << "is not supported by this sensor";
128  return false;
129  }
130 
131  // To set an option to a different value, we can call set_option with a new value
132  try {
133  value = sensor->get_option(option);
134  } catch (const rs2::error& e) {
135  // Some options can only be set while the camera is streaming,
136  // and generally the hardware might fail so it is good practice to catch exceptions from set_option
137  yCError(REALSENSE2TRACKING) << "Failed to get option " << rs2_option_to_string(option) << ". (" << e.what() << ")";
138  return false;
139  }
140  return true;
141 }
142 
143 static void settingErrorMsg(const string& error, bool& ret)
144 {
145  yCError(REALSENSE2TRACKING) << error.c_str();
146  ret = false;
147 }
148 #endif
149 
151 {
152 }
153 
154 bool realsense2Tracking::pipelineStartup()
155 {
156  try {
157  m_profile = m_pipeline.start(m_cfg);
158  } catch (const rs2::error& e) {
159  yCError(REALSENSE2TRACKING) << "Failed to start the pipeline:"
160  << "(" << e.what() << ")";
161  m_lastError = e.what();
162  return false;
163  }
164  return true;
165 }
166 
167 bool realsense2Tracking::pipelineShutdown()
168 {
169  try {
170  m_pipeline.stop();
171  } catch (const rs2::error& e) {
172  yCError(REALSENSE2TRACKING) << "Failed to stop the pipeline:"
173  << "(" << e.what() << ")";
174  m_lastError = e.what();
175  return false;
176  }
177  return true;
178 }
179 
180 bool realsense2Tracking::pipelineRestart()
181 {
182  std::lock_guard<std::mutex> guard(m_mutex);
183  if (!pipelineShutdown())
184  return false;
185 
186  return pipelineStartup();
187 }
188 
190 {
191  yCWarning(REALSENSE2TRACKING) << "This software module is experimental.";
192  yCWarning(REALSENSE2TRACKING) << "It is provided with uncomplete documentation and it may be modified/renamed/removed without any notice.";
193 
194  string sensor_is = "t265";
195  m_timestamp_type = timestamp_enumtype::yarp_timestamp;
196  if (config.check("timestamp"))
197  {
198  string temp = config.find("timestamp").asString();
199  if (temp == "yarp") m_timestamp_type = timestamp_enumtype::yarp_timestamp;
200  if (temp == "realsense") m_timestamp_type = timestamp_enumtype::rs_timestamp;
201  else
202  {
203  yCError(REALSENSE2TRACKING) << "Invalid value for option 'timestamp'. Valid values are 'yarp','realsense'";
204  return false;
205  }
206  }
207 
208  bool b= true;
209 
210  m_cfg.enable_stream(RS2_STREAM_ACCEL, RS2_FORMAT_MOTION_XYZ32F);
211  m_cfg.enable_stream(RS2_STREAM_GYRO, RS2_FORMAT_MOTION_XYZ32F);
212  m_cfg.enable_stream(RS2_STREAM_POSE, RS2_FORMAT_6DOF);
213  b &= pipelineStartup();
214  if (b==false)
215  {
216  yCError(REALSENSE2TRACKING) << "Pipeline initialization failed";
217  return false;
218  }
219 
220  return true;
221 }
222 
224 {
225  pipelineShutdown();
226  return true;
227 }
228 
229 //---------------------------------------------------------------------------------------------------------------
230 /* IThreeAxisGyroscopes methods */
232 {
233  return 1;
234 }
235 
237 {
238  if (sens_index != 0) { return yarp::dev::MAS_status::MAS_UNKNOWN; }
240 }
241 
242 bool realsense2Tracking::getThreeAxisGyroscopeName(size_t sens_index, std::string& name) const
243 {
244  if (sens_index != 0) { return false; }
245  name = m_inertial_sensor_name_prefix + "/" + m_gyro_sensor_tag;
246  return true;
247 }
248 
249 bool realsense2Tracking::getThreeAxisGyroscopeFrameName(size_t sens_index, std::string& frameName) const
250 {
251  if (sens_index != 0) { return false; }
252  frameName = m_gyroFrameName;
253  return true;
254 }
255 
256 bool realsense2Tracking::getThreeAxisGyroscopeMeasure(size_t sens_index, yarp::sig::Vector& out, double& timestamp) const
257 {
258  if (sens_index != 0) {
259  return false;
260  }
261 
262  std::lock_guard<std::mutex> guard(m_mutex);
263  rs2::frameset dataframe = m_pipeline.wait_for_frames();
264  auto fg = dataframe.first_or_default(RS2_STREAM_GYRO, RS2_FORMAT_MOTION_XYZ32F);
265  rs2::motion_frame gyro = fg.as<rs2::motion_frame>();
266  if (m_timestamp_type == yarp_timestamp) { timestamp = yarp::os::Time::now(); }
267  else if (m_timestamp_type == rs_timestamp) { timestamp = gyro.get_timestamp(); }
268  else timestamp=0;
269  m_last_gyro = gyro.get_motion_data();
270  out.resize(3);
271  out[0] = m_last_gyro.x;
272  out[1] = m_last_gyro.y;
273  out[2] = m_last_gyro.z;
274  return true;
275 }
276 
277 //-------------------------------------------------------------------------------------------------------
278 
279 /* IThreeAxisLinearAccelerometers methods */
281 {
282  return 1;
283 }
284 
286 {
287  if (sens_index != 0) { return yarp::dev::MAS_status::MAS_UNKNOWN; }
289 }
290 
291 bool realsense2Tracking::getThreeAxisLinearAccelerometerName(size_t sens_index, std::string& name) const
292 {
293  if (sens_index != 0) { return false; }
294  name = m_inertial_sensor_name_prefix + "/" + m_accel_sensor_tag;
295  return true;
296 }
297 
298 bool realsense2Tracking::getThreeAxisLinearAccelerometerFrameName(size_t sens_index, std::string& frameName) const
299 {
300  if (sens_index != 0) { return false; }
301  frameName = m_accelFrameName;
302  return true;
303 }
304 
305 bool realsense2Tracking::getThreeAxisLinearAccelerometerMeasure(size_t sens_index, yarp::sig::Vector& out, double& timestamp) const
306 {
307  if (sens_index != 0) { return false; }
308 
309  std::lock_guard<std::mutex> guard(m_mutex);
310  rs2::frameset dataframe = m_pipeline.wait_for_frames();
311  auto fa = dataframe.first_or_default(RS2_STREAM_ACCEL, RS2_FORMAT_MOTION_XYZ32F);
312  rs2::motion_frame accel = fa.as<rs2::motion_frame>();
313  m_last_accel = accel.get_motion_data();
314  if (m_timestamp_type == yarp_timestamp) { timestamp = yarp::os::Time::now(); }
315  else if (m_timestamp_type == rs_timestamp) { timestamp = accel.get_timestamp(); }
316  else timestamp = 0;
317  out.resize(3);
318  out[0] = m_last_accel.x;
319  out[1] = m_last_accel.y;
320  out[2] = m_last_accel.z;
321  return true;
322 }
323 
324 //-------------------------------------------------------------------------------------------------------
325 
326 /* IOrientationSensors methods */
328 {
329  return 1;
330 }
331 
333 {
334  if (sens_index != 0) { return yarp::dev::MAS_status::MAS_UNKNOWN; }
336 }
337 
338 bool realsense2Tracking::getOrientationSensorName(size_t sens_index, std::string& name) const
339 {
340  if (sens_index != 0) { return false; }
341  name = m_inertial_sensor_name_prefix + "/" + m_orientation_sensor_tag;
342  return true;
343 }
344 
345 bool realsense2Tracking::getOrientationSensorFrameName(size_t sens_index, std::string& frameName) const
346 {
347  if (sens_index != 0) { return false; }
348  frameName = m_orientationFrameName;
349  return true;
350 }
351 
352 
353 bool realsense2Tracking::getOrientationSensorMeasureAsRollPitchYaw(size_t sens_index, yarp::sig::Vector& rpy, double& timestamp) const
354 {
355  if (sens_index != 0) { return false; }
356 
357  std::lock_guard<std::mutex> guard(m_mutex);
358  rs2::frameset dataframe = m_pipeline.wait_for_frames();
359  auto fa = dataframe.first_or_default(RS2_STREAM_POSE);
360  rs2::pose_frame pose = fa.as<rs2::pose_frame>();
361  m_last_pose = pose.get_pose_data();
362  if (m_timestamp_type == yarp_timestamp) { timestamp = yarp::os::Time::now(); }
363  else if (m_timestamp_type == rs_timestamp) { timestamp = pose.get_timestamp(); }
364  else timestamp = 0;
365  yarp::math::Quaternion q(m_last_pose.rotation.x, m_last_pose.rotation.y, m_last_pose.rotation.z, m_last_pose.rotation.w);
367  yarp::sig::Vector rpy_temp = yarp::math::dcm2rpy(mat);
368  rpy.resize(3);
369  rpy[0] = 0 + rpy_temp[0] * 180 / M_PI; //here we can eventually adjust the sign and/or sum an offset
370  rpy[1] = 0 + rpy_temp[1] * 180 / M_PI;
371  rpy[2] = 0 + rpy_temp[2] * 180 / M_PI;
372  return true;
373 }
374 
375 //-------------------------------------------------------------------------------------------------------
376 
377 /* IPositionSensors methods */
379 {
380  return 1;
381 }
382 
384 {
385  if (sens_index != 0) { return yarp::dev::MAS_status::MAS_UNKNOWN; }
387 }
388 
389 bool realsense2Tracking::getPositionSensorName(size_t sens_index, std::string& name) const
390 {
391  if (sens_index != 0) { return false; }
392  name = m_inertial_sensor_name_prefix + "/" + m_pose_sensor_tag;
393  return true;
394 }
395 
396 bool realsense2Tracking::getPositionSensorFrameName(size_t sens_index, std::string& frameName) const
397 {
398  if (sens_index != 0) { return false; }
399  frameName = m_poseFrameName;
400  return true;
401 }
402 
403 
404 bool realsense2Tracking::getPositionSensorMeasure(size_t sens_index, yarp::sig::Vector& xyz, double& timestamp) const
405 {
406  if (sens_index != 0) { return false; }
407 
408  std::lock_guard<std::mutex> guard(m_mutex);
409  rs2::frameset dataframe = m_pipeline.wait_for_frames();
410  auto fa = dataframe.first_or_default(RS2_STREAM_POSE);
411  rs2::pose_frame pose = fa.as<rs2::pose_frame>();
412  m_last_pose = pose.get_pose_data();
413  if (m_timestamp_type == yarp_timestamp) { timestamp = yarp::os::Time::now(); }
414  else if (m_timestamp_type == rs_timestamp) { timestamp = pose.get_timestamp(); }
415  else timestamp = 0;
416  xyz.resize(3);
417  xyz[0] = m_last_pose.translation.x;
418  xyz[1] = m_last_pose.translation.y;
419  xyz[2] = m_last_pose.translation.z;
420  return true;
421 }
422 
423 //-------------------------------------------------------------------------------------------------------
424 #if 0
425 /* IPoseSensors methods */
426 size_t realsense2Tracking::getNrOfPoseSensors() const
427 {
428  return 1;
429 }
430 
431 yarp::dev::MAS_status realsense2Tracking::getPoseSensorStatus(size_t sens_index) const
432 {
433  if (sens_index != 0) { return yarp::dev::MAS_status::MAS_UNKNOWN; }
435 }
436 
437 bool realsense2Tracking::getPoseSensorName(size_t sens_index, std::string& name) const
438 {
439  if (sens_index != 0) { return false; }
440  name = m_inertial_sensor_name_prefix + "/" + m_pose_sensor_tag;
441  return true;
442 }
443 
444 bool realsense2Tracking::getPoseSensorFrameName(size_t sens_index, std::string& frameName) const
445 {
446  if (sens_index != 0) { return false; }
447  frameName = m_poseFrameName;
448  return true;
449 }
450 
451 bool realsense2Tracking::getPoseSensorMeasureAsXYZRPY(size_t sens_index, yarp::sig::Vector& xyzrpy, double& timestamp) const
452 {
453  std::lock_guard<std::mutex> guard(m_mutex);
454  rs2::frameset dataframe = m_pipeline.wait_for_frames();
455  auto fa = dataframe.first_or_default(RS2_STREAM_ACCEL, RS2_FORMAT_MOTION_XYZ32F);
456  rs2::pose_frame pose = fa.as<rs2::pose_frame>();
457  m_last_pose = pose.get_pose_data();
458  xyzrpy.resize(6);
459  xyzrpy[0] = m_last_pose.translation.x;
460  xyzrpy[1] = m_last_pose.translation.y;
461  xyzrpy[2] = m_last_pose.translation.z;
462  yarp::math::Quaternion q(m_last_pose.rotation.x, m_last_pose.rotation.y, m_last_pose.rotation.z, m_last_pose.rotation.w);
463  yarp::sig::Matrix mat = q.toRotationMatrix3x3();
465  xyzrpy[3] = 0 + rpy[0] * 180 / M_PI;
466  xyzrpy[4] = 0 + rpy[1] * 180 / M_PI;
467  xyzrpy[5] = 0 + rpy[2] * 180 / M_PI;
468  return true;
469 }
470 #endif
471 //-----------------------------------------------------------------------------
float t
bool ret
yarp::dev::MAS_status getThreeAxisGyroscopeStatus(size_t sens_index) const override
Get the status of the specified sensor.
bool getThreeAxisLinearAccelerometerName(size_t sens_index, std::string &name) const override
Get the name of the specified sensor.
bool getThreeAxisLinearAccelerometerFrameName(size_t sens_index, std::string &frameName) const override
Get the name of the frame of the specified sensor.
size_t getNrOfPositionSensors() const override
Get the number of position sensors exposed by this device.
bool open(yarp::os::Searchable &config) override
Open the DeviceDriver.
bool getPositionSensorName(size_t sens_index, std::string &name) const override
Get the name of the specified sensor.
size_t getNrOfThreeAxisLinearAccelerometers() const override
Get the number of three axis linear accelerometers exposed by this device.
size_t getNrOfOrientationSensors() const override
Get the number of orientation sensors exposed by this device.
yarp::dev::MAS_status getOrientationSensorStatus(size_t sens_index) const override
Get the status of the specified sensor.
bool getThreeAxisLinearAccelerometerMeasure(size_t sens_index, yarp::sig::Vector &out, double &timestamp) const override
Get the last reading of the specified sensor.
bool close() override
Close the DeviceDriver.
bool getPositionSensorMeasure(size_t sens_index, yarp::sig::Vector &xyz, double &timestamp) const override
Get the last reading of the position sensor as x y z.
bool getThreeAxisGyroscopeName(size_t sens_index, std::string &name) const override
Get the name of the specified sensor.
bool getOrientationSensorFrameName(size_t sens_index, std::string &frameName) const override
Get the name of the frame of the specified sensor.
bool getThreeAxisGyroscopeFrameName(size_t sens_index, std::string &frameName) const override
Get the name of the frame of the specified sensor.
bool getPositionSensorFrameName(size_t sens_index, std::string &frameName) const override
Get the name of the frame of the specified sensor.
bool getOrientationSensorName(size_t sens_index, std::string &name) const override
Get the name of the specified sensor.
bool getOrientationSensorMeasureAsRollPitchYaw(size_t sens_index, yarp::sig::Vector &rpy, double &timestamp) const override
Get the last reading of the orientation sensor as roll pitch yaw.
yarp::dev::MAS_status getThreeAxisLinearAccelerometerStatus(size_t sens_index) const override
Get the status of the specified sensor.
bool getThreeAxisGyroscopeMeasure(size_t sens_index, yarp::sig::Vector &out, double &timestamp) const override
Get the last reading of the gyroscope.
yarp::dev::MAS_status getPositionSensorStatus(size_t sens_index) const override
Get the status of the specified sensor.
size_t getNrOfThreeAxisGyroscopes() const override
Get the number of three axis gyroscopes exposed by this sensor.
yarp::sig::Matrix toRotationMatrix3x3() const
Converts a quaternion to a rotation matrix.
Definition: Quaternion.cpp:230
A base class for nested structures that can be searched.
Definition: Searchable.h:69
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
virtual std::string asString() const
Get string value.
Definition: Value.cpp:237
A class for a Matrix.
Definition: Matrix.h:46
void resize(size_t size) override
Resize the vector.
Definition: Vector.h:254
#define M_PI
#define yCError(component,...)
Definition: LogComponent.h:157
#define yCWarning(component,...)
Definition: LogComponent.h:146
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:80
An interface for the device drivers.
MAS_status
Status of a given analog sensor exposed by a multiple analog sensors interface.
@ MAS_UNKNOWN
The sensor is in an unknown state.
@ MAS_OK
The sensor is working correctly.
yarp::sig::Vector dcm2rpy(const yarp::sig::Matrix &R)
Converts a dcm (direction cosine matrix) rotation matrix to roll-pitch-yaw angles (defined in Math....
Definition: math.cpp:780
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition: Time.cpp:124
An interface to the operating system, including Port based communication.
Signal processing.
Definition: Image.h:25
static bool setOption(rs2_option option, const rs2::sensor *sensor, float value)
static bool getOption(rs2_option option, const rs2::sensor *sensor, float &value)
static std::string get_device_information(const rs2::device &dev)
static void settingErrorMsg(const string &error, bool &ret)
void operator*=(float t)
float3 operator-(float t)
void add(float t1, float t2, float t3)
float3 operator*(float t)