realsense_node_factory.cpp
Go to the documentation of this file.
1 // License: Apache 2.0. See LICENSE file in root directory.
2 // Copyright(c) 2017 Intel Corporation. All Rights Reserved
3 
7 #include <iostream>
8 #include <map>
9 #include <mutex>
10 #include <condition_variable>
11 #include <signal.h>
12 #include <thread>
13 #include <regex>
14 
15 using namespace realsense2_camera;
16 
17 #define REALSENSE_ROS_EMBEDDED_VERSION_STR (VAR_ARG_STRING(VERSION: REALSENSE_ROS_MAJOR_VERSION.REALSENSE_ROS_MINOR_VERSION.REALSENSE_ROS_PATCH_VERSION))
19 
21 
22 std::string api_version_to_string(int version)
23 {
24  std::ostringstream ss;
25  if (version / 10000 == 0)
26  ss << version;
27  else
28  ss << (version / 10000) << "." << (version % 10000) / 100 << "." << (version % 100);
29  return ss.str();
30 }
31 
33  _is_alive(true)
34 {
35  rs2_error* e = nullptr;
36  std::string running_librealsense_version(api_version_to_string(rs2_get_api_version(&e)));
37  ROS_INFO("RealSense ROS v%s", REALSENSE_ROS_VERSION_STR);
38  ROS_INFO("Built with LibRealSense v%s", RS2_API_VERSION_STR);
39  ROS_INFO_STREAM("Running with LibRealSense v" << running_librealsense_version);
40  if (RS2_API_VERSION_STR != running_librealsense_version)
41  {
42  ROS_WARN("***************************************************");
43  ROS_WARN("** running with a different librealsense version **");
44  ROS_WARN("** than the one the wrapper was compiled with! **");
45  ROS_WARN("***************************************************");
46  }
47 
48  auto severity = rs2_log_severity::RS2_LOG_SEVERITY_WARN;
50  if (rs2_log_severity::RS2_LOG_SEVERITY_DEBUG == severity)
52 
54 }
55 
57 {
58  _is_alive = false;
59  if (_query_thread.joinable())
60  {
61  _query_thread.join();
62  }
63 }
64 
65 std::string RealSenseNodeFactory::parse_usb_port(std::string line)
66 {
67  std::string port_id;
68  std::regex self_regex("(?:[^ ]+/usb[0-9]+[0-9./-]*/){0,1}([0-9.-]+)(:){0,1}[^ ]*", std::regex_constants::ECMAScript);
69  std::smatch base_match;
70  bool found = std::regex_match(line, base_match, self_regex);
71  if (found)
72  {
73  port_id = base_match[1].str();
74  if (base_match[2].str().size() == 0) //This is libuvc string. Remove counter is exists.
75  {
76  std::regex end_regex = std::regex(".+(-[0-9]+$)", std::regex_constants::ECMAScript);
77  bool found_end = std::regex_match(port_id, base_match, end_regex);
78  if (found_end)
79  {
80  port_id = port_id.substr(0, port_id.size() - base_match[1].str().size());
81  }
82  }
83  }
84  return port_id;
85 }
86 
88 {
89  if (!_device)
90  {
91  if (0 == list.size())
92  {
93  ROS_WARN("No RealSense devices were found!");
94  }
95  else
96  {
97  bool found = false;
98  ROS_INFO_STREAM(" ");
99  for (size_t count = 0; count < list.size(); count++)
100  {
102  try
103  {
104  dev = list[count];
105  }
106  catch(const std::exception& ex)
107  {
108  ROS_WARN_STREAM("Device " << count+1 << "/" << list.size() << " failed with exception: " << ex.what());
109  continue;
110  }
111  auto sn = dev.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER);
112  ROS_INFO_STREAM("Device with serial number " << sn << " was found."<<std::endl);
113  std::string pn = dev.get_info(RS2_CAMERA_INFO_PHYSICAL_PORT);
114  std::string name = dev.get_info(RS2_CAMERA_INFO_NAME);
115  ROS_INFO_STREAM("Device with physical ID " << pn << " was found.");
116  std::vector<std::string> results;
117  ROS_INFO_STREAM("Device with name " << name << " was found.");
118  std::string port_id = parse_usb_port(pn);
119  if (port_id.empty())
120  {
121  std::stringstream msg;
122  msg << "Error extracting usb port from device with physical ID: " << pn << std::endl << "Please report on github issue at https://github.com/IntelRealSense/realsense-ros";
123  if (_usb_port_id.empty())
124  {
125  ROS_WARN_STREAM(msg.str());
126  }
127  else
128  {
129  ROS_ERROR_STREAM(msg.str());
130  ROS_ERROR_STREAM("Please use serial number instead of usb port.");
131  }
132  }
133  else
134  {
135  ROS_INFO_STREAM("Device with port number " << port_id << " was found.");
136  }
137  bool found_device_type(true);
138  if (!_device_type.empty())
139  {
140  std::smatch match_results;
141  std::regex device_type_regex(_device_type.c_str(), std::regex::icase);
142  found_device_type = std::regex_search(name, match_results, device_type_regex);
143  }
144 
145  if ((_serial_no.empty() || sn == _serial_no) && (_usb_port_id.empty() || port_id == _usb_port_id) && found_device_type)
146  {
147  _device = dev;
148  _serial_no = sn;
149  found = true;
150  break;
151  }
152  }
153  if (!found)
154  {
155  // T265 could be caught by another node.
156  std::string msg ("The requested device with ");
157  bool add_and(false);
158  if (!_serial_no.empty())
159  {
160  msg += "serial number " + _serial_no;
161  add_and = true;
162  }
163  if (!_usb_port_id.empty())
164  {
165  if (add_and)
166  {
167  msg += " and ";
168  }
169  msg += "usb port id " + _usb_port_id;
170  add_and = true;
171  }
172  if (!_device_type.empty())
173  {
174  if (add_and)
175  {
176  msg += " and ";
177  }
178  msg += "device name containing " + _device_type;
179  }
180  msg += " is NOT found. Will Try again.";
182  }
183  else
184  {
186  {
187  std::string usb_type = _device.get_info(RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR);
188  ROS_INFO_STREAM("Device USB type: " << usb_type);
189  if (usb_type.find("2.") != std::string::npos)
190  {
191  ROS_WARN_STREAM("Device " << _serial_no << " is connected using a " << usb_type << " port. Reduced performance is expected.");
192  }
193  }
194  }
195  }
196  }
197 
198  bool remove_tm2_handle(_device && RS_T265_PID != std::stoi(_device.get_info(RS2_CAMERA_INFO_PRODUCT_ID), 0, 16));
199  if (remove_tm2_handle)
200  {
202  }
203 
204  if (_device && _initial_reset)
205  {
206  _initial_reset = false;
207  try
208  {
209  ROS_INFO("Resetting device...");
211  _device = rs2::device();
212  }
213  catch(const std::exception& ex)
214  {
215  ROS_WARN_STREAM("An exception has been thrown: " << ex.what());
216  }
217  }
218 }
219 
221 {
222  if (info.was_removed(_device))
223  {
224  ROS_ERROR("The device has been disconnected!");
225  reset();
226  }
227 }
228 
229 bool RealSenseNodeFactory::toggle_sensor_callback(std_srvs::SetBool::Request &req, std_srvs::SetBool::Response &res)
230 {
231  if (req.data)
232  ROS_INFO_STREAM("toggling sensor : ON");
233  else
234  ROS_INFO_STREAM("toggling sensor : OFF");
235  _realSenseNode->toggleSensors(req.data);
236  res.success=true;
237  return true;
238 }
239 
241 {
242  auto nh = getNodeHandle();
243  _init_timer = nh.createWallTimer(ros::WallDuration(0.01), &RealSenseNodeFactory::initialize, this, true);
244 }
245 
247 {
248  _device = rs2::device();
249  try
250  {
251 #ifdef BPDEBUG
252  std::cout << "Attach to Process: " << getpid() << std::endl;
253  std::cout << "Press <ENTER> key to continue." << std::endl;
254  std::cin.get();
255 #endif
257  auto privateNh = getPrivateNodeHandle();
258  privateNh.param("serial_no", _serial_no, std::string(""));
259  privateNh.param("usb_port_id", _usb_port_id, std::string(""));
260  privateNh.param("device_type", _device_type, std::string(""));
261 
262  if (!toggle_sensor_srv)
263  {
265  }
266  std::string rosbag_filename("");
267  privateNh.param("rosbag_filename", rosbag_filename, std::string(""));
268 
269  if (!rosbag_filename.empty())
270  {
271  {
272  ROS_INFO_STREAM("publish topics from rosbag file: " << rosbag_filename.c_str());
273  auto pipe = std::make_shared<rs2::pipeline>();
275  cfg.enable_device_from_file(rosbag_filename.c_str(), false);
276  cfg.enable_all_streams();
277  pipe->start(cfg); //File will be opened in read mode at this point
278  _device = pipe->get_active_profile().get_device();
280  }
281  if (_device)
282  {
283  StartDevice();
284  }
285  }
286  else
287  {
288  privateNh.param("initial_reset", _initial_reset, false);
289 
290  _is_alive = true;
291  _query_thread = std::thread([=]()
292  {
293  double reconnect_timeout;
294  privateNh.param("reconnect_timeout", reconnect_timeout, 6.0);
295  double wait_for_device_timeout;
296  privateNh.param("wait_for_device_timeout", wait_for_device_timeout, -1.0);
297  std::chrono::milliseconds timespan(static_cast<int>(reconnect_timeout*1e3));
298  ros::Time first_try_time = ros::Time::now();
299  while (_is_alive && !_device)
300  {
302  if (_device)
303  {
304  std::function<void(rs2::event_information&)> change_device_callback_function = [this](rs2::event_information& info){change_device_callback(info);};
305  _ctx.set_devices_changed_callback(change_device_callback_function);
306  StartDevice();
307  }
308  else
309  {
310  std::chrono::milliseconds actual_timespan(timespan);
311  if (wait_for_device_timeout > 0)
312  {
313  auto time_to_timeout(wait_for_device_timeout - (ros::Time::now() - first_try_time).toSec());
314  if (time_to_timeout < 0)
315  {
316  ROS_ERROR_STREAM("wait for device timeout of " << wait_for_device_timeout << " secs expired");
317  exit(1);
318  }
319  else
320  {
321  double max_timespan_secs(std::chrono::duration_cast<std::chrono::seconds>(timespan).count());
322  actual_timespan = std::chrono::milliseconds (static_cast<int>(std::min(max_timespan_secs, time_to_timeout) * 1e3));
323  }
324  }
325  std::this_thread::sleep_for(actual_timespan);
326  }
327  }
328  });
329  if (!_reset_srv)
330  {
331  _reset_srv = privateNh.advertiseService("reset", &RealSenseNodeFactory::handleReset, this);
332  }
333  }
334  }
335  catch(const std::exception& ex)
336  {
337  ROS_ERROR_STREAM("An exception has been thrown: " << ex.what());
338  exit(1);
339  }
340  catch(...)
341  {
342  ROS_ERROR_STREAM("Unknown exception has occured!");
343  exit(1);
344  }
345 }
346 
348 {
349  if (_realSenseNode) _realSenseNode.reset();
350  try
351  {
354  // TODO
355  std::string pid_str(_device.get_info(RS2_CAMERA_INFO_PRODUCT_ID));
356  uint16_t pid = std::stoi(pid_str, 0, 16);
357  switch(pid)
358  {
359  case SR300_PID:
360  case SR300v2_PID:
361  case RS400_PID:
362  case RS405_PID:
363  case RS410_PID:
364  case RS460_PID:
365  case RS415_PID:
366  case RS420_PID:
367  case RS420_MM_PID:
368  case RS430_PID:
369  case RS430_MM_PID:
370  case RS430_MM_RGB_PID:
371  case RS435_RGB_PID:
372  case RS435i_RGB_PID:
373  case RS455_PID:
374  case RS465_PID:
375  case RS_USB2_PID:
376  case RS_L515_PID_PRE_PRQ:
377  case RS_L515_PID:
378  case RS_L535_PID:
379  _realSenseNode = std::shared_ptr<BaseRealSenseNode>(new BaseRealSenseNode(nh, privateNh, _device, _serial_no));
380  break;
381  case RS_T265_PID:
382  _realSenseNode = std::shared_ptr<T265RealsenseNode>(new T265RealsenseNode(nh, privateNh, _device, _serial_no));
383  break;
384  default:
385  ROS_FATAL_STREAM("Unsupported device!" << " Product ID: 0x" << pid_str);
386  ros::shutdown();
387  exit(1);
388  }
390  _realSenseNode->publishTopics();
391  }
392  catch (const rs2::error& e)
393  {
394  ROS_ERROR_STREAM("Exception: " << e.what());
395  }
396 }
397 
399 {
400  _is_alive = false;
401  if (_query_thread.joinable())
402  {
403  _query_thread.join();
404  }
405 
406  try
407  {
408  _realSenseNode.reset();
409  if (_device)
410  {
412  _device = rs2::device();
413  }
414  }
415  catch (const rs2::error& e)
416  {
417  ROS_ERROR_STREAM("Exception: " << e.what());
418  }
419 
421 }
422 
423 bool RealSenseNodeFactory::handleReset(std_srvs::Empty::Request& request, std_srvs::Empty::Response& response)
424 {
425  reset();
426  return true;
427 }
428 
430 {
431  static const char* severity_var_name = "LRS_LOG_LEVEL";
432  auto content = getenv(severity_var_name);
433 
434  if (content)
435  {
436  std::string content_str(content);
437  std::transform(content_str.begin(), content_str.end(), content_str.begin(), ::toupper);
438 
439  for (uint32_t i = 0; i < RS2_LOG_SEVERITY_COUNT; i++)
440  {
441  auto current = std::string(rs2_log_severity_to_string((rs2_log_severity)i));
442  std::transform(current.begin(), current.end(), current.begin(), ::toupper);
443  if (content_str == current)
444  {
446  break;
447  }
448  }
449  }
450 }
rs2::device
RS2_CAMERA_INFO_PHYSICAL_PORT
RS2_CAMERA_INFO_PHYSICAL_PORT
assert
count
GLint GLsizei count
name
realsense2_camera::RealSenseNodeFactory::getDevice
void getDevice(rs2::device_list list)
Definition: realsense_node_factory.cpp:87
realsense2_camera::RS460_PID
const uint16_t RS460_PID
Definition: constants.h:32
realsense_ros_camera_version
constexpr auto realsense_ros_camera_version
Definition: realsense_node_factory.cpp:18
msg
msg
str
str(const bytes &b)
nodelet::Nodelet::getNodeHandle
ros::NodeHandle & getNodeHandle() const
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(args)
realsense2_camera::RS435i_RGB_PID
const uint16_t RS435i_RGB_PID
Definition: constants.h:34
realsense2_camera::RealSenseNodeFactory::_init_timer
ros::WallTimer _init_timer
Definition: realsense_node_factory.h:86
RS2_CAMERA_INFO_SERIAL_NUMBER
RS2_CAMERA_INFO_SERIAL_NUMBER
uint16_t
unsigned short uint16_t
list
realsense2_camera::RealSenseNodeFactory::_is_alive
bool _is_alive
Definition: realsense_node_factory.h:84
realsense_node_factory.h
realsense2_camera::RS400_PID
const uint16_t RS400_PID
Definition: constants.h:21
ROS_FATAL_STREAM
#define ROS_FATAL_STREAM(args)
info
def info(*args)
rs2_error
realsense2_camera::RealSenseNodeFactory::tryGetLogSeverity
void tryGetLogSeverity(rs2_log_severity &severity) const
Definition: realsense_node_factory.cpp:429
realsense2_camera::RS465_PID
const uint16_t RS465_PID
Definition: constants.h:35
realsense2_camera::RealSenseNodeFactory::_initial_reset
bool _initial_reset
Definition: realsense_node_factory.h:82
rs2::device_list
void
typedef void(APIENTRY *GLDEBUGPROC)(GLenum source
ros::shutdown
ROSCPP_DECL void shutdown()
ros::NodeHandle::advertiseService
ServiceServer advertiseService(AdvertiseServiceOptions &ops)
cfg
cfg
realsense2_camera::RealSenseNodeFactory::parse_usb_port
static std::string parse_usb_port(std::string line)
Definition: realsense_node_factory.cpp:65
realsense2_camera::RealSenseNodeFactory::change_device_callback
void change_device_callback(rs2::event_information &info)
Definition: realsense_node_factory.cpp:220
realsense2_camera::BaseRealSenseNode
Definition: base_realsense_node.h:120
realsense2_camera::RS415_PID
const uint16_t RS415_PID
Definition: constants.h:23
realsense2_camera::RS_USB2_PID
const uint16_t RS_USB2_PID
Definition: constants.h:26
ros::console::set_logger_level
ROSCONSOLE_DECL bool set_logger_level(const std::string &name, levels::Level level)
rs2_log_severity
rs2_log_severity
rs2::device::supports
bool supports(rs2_camera_info info) const
RS2_CAMERA_INFO_PRODUCT_ID
RS2_CAMERA_INFO_PRODUCT_ID
realsense2_camera::RealSenseNodeFactory::toggle_sensor_callback
bool toggle_sensor_callback(std_srvs::SetBool::Request &req, std_srvs::SetBool::Response &res)
Definition: realsense_node_factory.cpp:229
base_realsense_node.h
nodelet::Nodelet::getPrivateNodeHandle
ros::NodeHandle & getPrivateNodeHandle() const
realsense2_camera::RealSenseNodeFactory::StartDevice
void StartDevice()
Definition: realsense_node_factory.cpp:347
realsense2_camera::RS430_PID
const uint16_t RS430_PID
Definition: constants.h:24
RS2_CAMERA_INFO_NAME
RS2_CAMERA_INFO_NAME
realsense2_camera::RS430_MM_RGB_PID
const uint16_t RS430_MM_RGB_PID
Definition: constants.h:31
realsense2_camera::RS435_RGB_PID
const uint16_t RS435_RGB_PID
Definition: constants.h:33
realsense2_camera::RS_T265_PID
const uint16_t RS_T265_PID
Definition: constants.h:39
realsense2_camera::RS_L535_PID
const uint16_t RS_L535_PID
Definition: constants.h:42
size
GLsizeiptr size
realsense2_camera::RealSenseNodeFactory::_device_type
std::string _device_type
Definition: realsense_node_factory.h:81
realsense2_camera::RealSenseNodeFactory::toggle_sensor_srv
ros::ServiceServer toggle_sensor_srv
Definition: realsense_node_factory.h:85
realsense2_camera::RS_L515_PID_PRE_PRQ
const uint16_t RS_L515_PID_PRE_PRQ
Definition: constants.h:40
list::size
size_t size() const
realsense2_camera::RealSenseNodeFactory::_ctx
rs2::context _ctx
Definition: realsense_node_factory.h:78
ROS_WARN_STREAM
#define ROS_WARN_STREAM(args)
dev
dev
ros::console::levels::Debug
Debug
uint32_t
unsigned int uint32_t
realsense2_camera::SR300v2_PID
const uint16_t SR300v2_PID
Definition: constants.h:20
realsense2_camera::RS420_MM_PID
const uint16_t RS420_MM_PID
Definition: constants.h:28
realsense2_camera::RealSenseNodeFactory::onInit
virtual void onInit() override
Definition: realsense_node_factory.cpp:240
realsense2_camera::RealSenseNodeFactory::~RealSenseNodeFactory
virtual ~RealSenseNodeFactory()
Definition: realsense_node_factory.cpp:56
PLUGINLIB_EXPORT_CLASS
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
REALSENSE_ROS_EMBEDDED_VERSION_STR
#define REALSENSE_ROS_EMBEDDED_VERSION_STR
Definition: realsense_node_factory.cpp:17
rs2_log_severity_to_string
const char * rs2_log_severity_to_string(rs2_log_severity severity)
rs2::log_to_console
void log_to_console(rs2_log_severity min_severity)
realsense2_camera::RealSenseNodeFactory::_reset_srv
ros::ServiceServer _reset_srv
Definition: realsense_node_factory.h:87
realsense2_camera::RealSenseNodeFactory
Definition: realsense_node_factory.h:57
realsense2_camera::RS430_MM_PID
const uint16_t RS430_MM_PID
Definition: constants.h:25
rs2::config
rs2::device::hardware_reset
void hardware_reset()
res
GLuint res
severity
GLenum GLuint GLenum severity
ROS_WARN
#define ROS_WARN(...)
realsense2_camera::RealSenseNodeFactory::_device
rs2::device _device
Definition: realsense_node_factory.h:76
realsense2_camera::RS420_PID
const uint16_t RS420_PID
Definition: constants.h:27
ROS_INFO_STREAM
#define ROS_INFO_STREAM(args)
line
string line
rs2::context::unload_tracking_module
void unload_tracking_module()
realsense2_camera::RealSenseNodeFactory::reset
void reset()
Definition: realsense_node_factory.cpp:398
realsense2_camera::RS_L515_PID
const uint16_t RS_L515_PID
Definition: constants.h:41
realsense2_camera::RealSenseNodeFactory::_usb_port_id
std::string _usb_port_id
Definition: realsense_node_factory.h:80
pipe
pipe
RS2_API_VERSION_STR
#define RS2_API_VERSION_STR
RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR
RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR
realsense2_camera::RS405_PID
const uint16_t RS405_PID
Definition: constants.h:37
realsense2_camera::RS455_PID
const uint16_t RS455_PID
Definition: constants.h:38
realsense2_camera::RealSenseNodeFactory::_serial_no
std::string _serial_no
Definition: realsense_node_factory.h:79
i
D const & i
ros::WallTimerEvent
nodelet::Nodelet
ros::Time
realsense2_camera::RealSenseNodeFactory::initialize
void initialize(const ros::WallTimerEvent &ignored)
Definition: realsense_node_factory.cpp:246
api_version_to_string
std::string api_version_to_string(int version)
Definition: realsense_node_factory.cpp:22
realsense2_camera
Definition: base_realsense_node.h:27
std::stoi
int stoi(const std::string &value)
rs2::event_information
std
rs2::error
realsense2_camera::RealSenseNodeFactory::_realSenseNode
std::shared_ptr< InterfaceRealSenseNode > _realSenseNode
Definition: realsense_node_factory.h:77
rs2::context::query_devices
device_list query_devices() const
ROS_ERROR
#define ROS_ERROR(...)
realsense2_camera::T265RealsenseNode
Definition: t265_realsense_node.h:7
realsense2_camera::RealSenseNodeFactory::RealSenseNodeFactory
RealSenseNodeFactory()
Definition: realsense_node_factory.cpp:32
e
e
realsense2_camera::RealSenseNodeFactory::handleReset
bool handleReset(std_srvs::Empty::Request &request, std_srvs::Empty::Response &response)
Definition: realsense_node_factory.cpp:423
REALSENSE_ROS_VERSION_STR
#define REALSENSE_ROS_VERSION_STR
Definition: constants.h:15
realsense2_camera::RealSenseNodeFactory::_query_thread
std::thread _query_thread
Definition: realsense_node_factory.h:83
rs2::device::get_info
const char * get_info(rs2_camera_info info) const
rs2::context::set_devices_changed_callback
void set_devices_changed_callback(T callback)
ROSCONSOLE_DEFAULT_NAME
#define ROSCONSOLE_DEFAULT_NAME
ros::WallDuration
ROS_INFO
#define ROS_INFO(...)
rs2_get_api_version
int rs2_get_api_version(rs2_error **error) BEGIN_API_CALL
RS2_LOG_SEVERITY_COUNT
RS2_LOG_SEVERITY_COUNT
ros::NodeHandle::createWallTimer
WallTimer createWallTimer(WallDuration period, const WallTimerCallback &callback, bool oneshot=false, bool autostart=true) const
realsense2_camera::SR300_PID
const uint16_t SR300_PID
Definition: constants.h:19
realsense2_camera::RS410_PID
const uint16_t RS410_PID
Definition: constants.h:22
ros::NodeHandle
t265_realsense_node.h
ros::Time::now
static Time now()


realsense2_camera
Author(s): Sergey Dorodnicov , Doron Hirshberg
autogenerated on Fri Mar 25 2022 02:15:35