1 #include "../include/base_realsense_node.h" 3 #include <boost/algorithm/string.hpp> 8 #include <dynamic_reconfigure/IntParameter.h> 9 #include <dynamic_reconfigure/Reconfigure.h> 10 #include <dynamic_reconfigure/Config.h> 16 #define STREAM_NAME(sip) (static_cast<std::ostringstream&&>(std::ostringstream() << _stream_name[sip.first] << ((sip.second>0) ? std::to_string(sip.second) : ""))).str() 17 #define FRAME_ID(sip) (static_cast<std::ostringstream&&>(std::ostringstream() << "camera_" << STREAM_NAME(sip) << "_frame")).str() 18 #define OPTICAL_FRAME_ID(sip) (static_cast<std::ostringstream&&>(std::ostringstream() << "camera_" << STREAM_NAME(sip) << "_optical_frame")).str() 19 #define ALIGNED_DEPTH_TO_FRAME_ID(sip) (static_cast<std::ostringstream&&>(std::ostringstream() << "camera_aligned_depth_to_" << STREAM_NAME(sip) << "_frame")).str() 22 _publisher(imu_publisher), _pause_mode(false),
23 _waiting_list_size(waiting_list_size)
33 std::lock_guard<std::mutex> lock_guard(
_mutex);
53 std::lock_guard<std::mutex> lock_guard(
_mutex);
59 std::lock_guard<std::mutex> lock_guard(
_mutex);
79 ns.erase(std::remove(ns.begin(), ns.end(),
'/'), ns.end());
86 const std::string& serial_no) :
87 _is_running(true), _base_frame_id(
""), _node_handle(nodeHandle),
88 _pnh(privateNodeHandle), _dev(dev), _json_file_path(
""),
89 _serial_no(serial_no),
90 _is_initialized_time_base(false),
91 _namespace(getNamespaceStr())
153 std::set<std::string> module_names;
159 std::pair< std::set<std::string>::iterator,
bool>
res = module_names.insert(module_name);
177 std::map<std::string, std::vector<rs2::stream_profile> >
profiles;
178 std::map<std::string, rs2::sensor> active_sensors;
183 <<
" to " << module_name);
184 profiles[module_name].insert(profiles[module_name].
begin(),
190 for (
const std::pair<std::string, std::vector<rs2::stream_profile> >& sensor_profile : profiles)
192 std::string module_name = sensor_profile.first;
194 sensor.
open(sensor_profile.second);
204 std::set<std::string> module_names;
208 std::pair< std::set<std::string>::iterator,
bool>
res = module_names.insert(module_name);
224 std::vector<std::string> error_strings({
"RT IC2 Config error",
225 "Left IC2 Config error"});
230 if (error_strings.end() != find_if(error_strings.begin(), error_strings.end(), [&n] (std::string err)
267 std::thread
t = std::thread([=]()
283 return op_range.
max == 1.0f &&
284 op_range.
min == 0.0f &&
285 op_range.
step == 1.0f;
290 static const int MAX_ENUM_OPTION_VALUES(100);
291 static const float EPSILON(0.05);
294 if (abs((op_range.
step - 1)) > EPSILON || (op_range.
max > MAX_ENUM_OPTION_VALUES))
return false;
295 for (
auto i = op_range.
min;
i <= op_range.
max;
i += op_range.
step)
307 return (op_range.
step == 1.0);
312 std::map<std::string, int>
dict;
316 const auto op_range_min = int(op_range.
min);
317 const auto op_range_max = int(op_range.
max);
318 const auto op_range_step = int(op_range.
step);
319 for (
auto val = op_range_min;
val <= op_range_max;
val += op_range_step)
332 template <
typename K,
typename V>
333 std::ostream& operator<<(std::ostream& os, const std::map<K, V>&
m)
336 for (
const auto& kv :
m)
338 os <<
" {" << kv.first <<
": " << kv.second <<
'}';
351 return std::isalnum(c) || c ==
'/' || c ==
'_';
360 std::string fixed_name = original_name;
361 std::transform(fixed_name.begin(), fixed_name.end(), fixed_name.begin(),
362 [](
unsigned char c) {
return std::tolower(
c); });
363 std::replace_if(fixed_name.begin(), fixed_name.end(), [](
const char c) {
return !
isValidCharInName(
c); },
371 if (option_name ==
"left")
372 auto_exposure_roi.
min_x = new_value;
373 else if (option_name ==
"right")
374 auto_exposure_roi.max_x = new_value;
375 else if (option_name ==
"top")
376 auto_exposure_roi.min_y = new_value;
377 else if (option_name ==
"bottom")
378 auto_exposure_roi.max_y = new_value;
381 ROS_WARN_STREAM(
"Invalid option_name: " << option_name <<
" while setting auto exposure ROI.");
394 catch(
const std::runtime_error&
e)
401 const std::string option_name,
const int min_val,
const int max_val,
rs2::sensor sensor,
404 nh1.
param(option_name, *option_value, *option_value);
405 if (*option_value < min_val) *option_value = min_val;
406 if (*option_value > max_val) *option_value = max_val;
408 ddynrec->registerVariable<
int>(
409 option_name, *option_value, [
this, sensor, option_name](
int new_value){
set_auto_exposure_roi(option_name, sensor, new_value);},
410 "auto-exposure " + option_name +
" coordinate", min_val, max_val);
426 std::shared_ptr<ddynamic_reconfigure::DDynamicReconfigure> ddynrec = std::make_shared<ddynamic_reconfigure::DDynamicReconfigure>(nh1);
435 ddynrec->publishServicesTopics();
449 std::shared_ptr<ddynamic_reconfigure::DDynamicReconfigure> ddynrec = std::make_shared<ddynamic_reconfigure::DDynamicReconfigure>(nh1);
462 auto option_value = bool(sensor.
get_option(option));
463 if (nh1.
param(option_name, option_value, option_value))
467 ddynrec->registerVariable<
bool>(
468 option_name, option_value,
469 [option, sensor](
bool new_value) { sensor.
set_option(option, new_value); },
474 if (enum_dict.empty())
477 const auto sensor_option_value = sensor.
get_option(option);
478 auto option_value = sensor_option_value;
479 if (nh1.
param(option_name, option_value, option_value))
481 if (option_value < op_range.
min || op_range.
max < option_value)
484 <<
" outside the range [" << op_range.
min <<
", " << op_range.
max 485 <<
"]. Using current sensor value " << sensor_option_value <<
" instead.");
486 option_value = sensor_option_value;
493 if (option_value < op_range.
min || op_range.
max < option_value)
496 <<
" that is not in range [" << op_range.
min <<
", " << op_range.
max <<
"]" 497 <<
". Removing this parameter from dynamic reconfigure options.");
502 ddynrec->registerVariable<
int>(
503 option_name, int(option_value),
504 [option, sensor](
int new_value) { sensor.
set_option(option, new_value); },
522 ddynrec->registerVariable<
double>(
523 option_name, option_value,
524 [option, sensor](
double new_value) { sensor.
set_option(option, new_value); },
531 const auto sensor_option_value = sensor.
get_option(option);
532 auto option_value = int(sensor_option_value);
533 if (nh1.
param(option_name, option_value, option_value))
535 if (std::find_if(enum_dict.cbegin(), enum_dict.cend(),
536 [&option_value](
const std::pair<std::string, int>& kv) {
537 return kv.second == option_value;
538 }) == enum_dict.cend())
541 <<
" that is not in the enum " << enum_dict
542 <<
". Using current sensor value " << sensor_option_value <<
" instead.");
543 option_value = sensor_option_value;
550 if (std::find_if(enum_dict.cbegin(), enum_dict.cend(),
551 [&option_value](
const std::pair<std::string, int>& kv) {
552 return kv.second == option_value;
553 }) == enum_dict.cend())
556 <<
" that is not in the enum " << enum_dict
557 <<
". Removing this parameter from dynamic reconfigure options.");
562 ddynrec->registerEnumVariable<
int>(
563 option_name, option_value,
564 [
this, option, sensor, module_name](
int new_value)
566 sensor.set_option(option, new_value);
573 sensor.get_option_description(option), enum_dict);
577 ddynrec->registerEnumVariable<
int>(
578 option_name, option_value,
579 [option, sensor](
int new_value) { sensor.
set_option(option, new_value); },
584 catch(
const rs2::backend_error&
e)
586 ROS_WARN_STREAM(
"Failed to set option: " << option_name <<
": " << e.what());
588 catch(
const std::exception& e)
590 std::cerr << e.what() <<
'\n';
594 ddynrec->publishServicesTopics();
600 ROS_INFO(
"Setting Dynamic reconfig parameters.");
611 std::string module_name = nfilter._name;
612 auto sensor = *(nfilter._filter);
616 ROS_INFO(
"Done Setting Dynamic reconfig parameters.");
624 std::string module_name;
632 for (
unsigned int seq_id = 1; seq_id <= seq_size; seq_id++ )
637 std::stringstream param_name_str;
639 std::string param_name(param_name_str.str());
643 int user_set_option_value;
644 _pnh.
param(param_name, user_set_option_value, option_value);
646 if (option_value != user_set_option_value)
664 dynamic_reconfigure::ReconfigureRequest srv_req;
665 dynamic_reconfigure::ReconfigureResponse srv_resp;
666 dynamic_reconfigure::IntParameter int_param;
667 dynamic_reconfigure::Config conf;
671 conf.ints.push_back(int_param);
673 srv_req.config = conf;
675 std::string service_name = module_name +
"/set_parameters";
677 ROS_INFO_STREAM(
"call to set " << service_name <<
"/" << int_param.name <<
" to " << int_param.value <<
" succeeded");
679 ROS_ERROR_STREAM(
"call to set " << service_name <<
"/" << int_param.name <<
" to " << int_param.value <<
" failed");
685 int time_interval(1000);
686 std::function<void()>
func = [
this, time_interval](){
688 std::unique_lock<std::mutex> lock(mu);
703 if (str ==
"RS2_STREAM_ANY")
705 if (str ==
"RS2_STREAM_COLOR")
707 if (str ==
"RS2_STREAM_INFRARED")
709 if (str ==
"RS2_STREAM_FISHEYE")
711 throw std::runtime_error(
"Unknown stream string " + str);
720 _pnh.
param(
"infra_rgb", infra_rgb,
false);
732 std::string pc_texture_stream(
"");
734 _pnh.
param(
"pointcloud_texture_stream", pc_texture_stream, std::string(
"RS2_STREAM_COLOR"));
735 _pnh.
param(
"pointcloud_texture_index", pc_texture_idx, 0);
778 std::vector<stream_index_pair>
streams(IMAGE_STREAMS);
779 streams.insert(streams.end(), HID_STREAMS.begin(), HID_STREAMS.end());
780 for (
auto&
stream : streams)
782 std::string param_name(static_cast<std::ostringstream&&>(std::ostringstream() <<
STREAM_NAME(
stream) <<
"_frame_id").
str());
785 param_name =
static_cast<std::ostringstream&&
>(std::ostringstream() <<
STREAM_NAME(stream) <<
"_optical_frame_id").
str();
790 std::string unite_imu_method_str(
"");
792 if (unite_imu_method_str ==
"linear_interpolation")
794 else if (unite_imu_method_str ==
"copy")
806 std::string param_name(static_cast<std::ostringstream&&>(std::ostringstream() <<
"aligned_depth_to_" <<
STREAM_NAME(stream) <<
"_frame_id").
str());
827 std::stringstream ss;
832 std::string json_file_content = ss.str();
842 ROS_WARN(
"Device does not support advanced settings!");
845 ROS_INFO(
"JSON file is not provided");
871 std::function<void(rs2::frame)> frame_callback_function, imu_callback_function;
874 frame_callback_function =
_syncer;
876 auto frame_callback_inner = [
this](
rs2::frame frame){
902 stream_index_pair sip(video_profile.stream_type(), video_profile.stream_index());
931 ROS_ERROR_STREAM(
"Module Name \"" << module_name <<
"\" isn't supported by LibRealSense! Terminating RealSense Node...");
939 for (std::pair<stream_index_pair, bool>
const&
enable :
_enable )
945 _enable[
enable.first] =
false;
949 catch(
const std::exception& ex)
970 std::stringstream image_raw, camera_info;
971 bool rectified_image =
false;
973 rectified_image =
true;
976 image_raw << stream_name <<
"/image_" << ((rectified_image)?
"rect_":
"") <<
"raw";
977 camera_info << stream_name <<
"/camera_info";
985 std::stringstream aligned_image_raw, aligned_camera_info;
986 aligned_image_raw <<
"aligned_depth_to_" << stream_name <<
"/image_raw";
987 aligned_camera_info <<
"aligned_depth_to_" << stream_name <<
"/camera_info";
989 std::string aligned_stream_name =
"aligned_depth_to_" + stream_name;
1059 auto profiles = sens.get_stream_profiles();
1065 "stream_type: " <<
rs2_stream_to_string(video_profile.stream_type()) <<
"(" << video_profile.stream_index() <<
")" <<
1066 "Format: " << video_profile.format() <<
1067 ", Width: " << video_profile.width() <<
1068 ", Height: " << video_profile.height() <<
1069 ", FPS: " << video_profile.fps());
1071 if (
profile.stream_type() == elem.first &&
profile.stream_index() == elem.second)
1077 if ((
_width[elem] == 0 || video_profile.width() ==
_width[elem]) &&
1078 (
_height[elem] == 0 || video_profile.height() ==
_height[elem]) &&
1079 (
_fps[elem] == 0 || video_profile.fps() ==
_fps[elem]) &&
1088 if (!selected_profile)
1092 ", Stream Index: " << elem.second <<
1093 ", Width: " <<
_width[elem] <<
1094 ", Height: " <<
_height[elem] <<
1095 ", FPS: " <<
_fps[elem] <<
1097 if (default_profile)
1100 selected_profile = default_profile;
1103 if (selected_profile)
1106 _width[elem] = video_profile.width();
1107 _height[elem] = video_profile.height();
1108 _fps[elem] = video_profile.fps();
1111 ROS_INFO_STREAM(
STREAM_NAME(elem) <<
" stream is enabled - width: " << _width[elem] <<
", height: " <<
_height[elem] <<
", fps: " <<
_fps[elem] <<
", " <<
"Format: " << video_profile.format());
1134 auto profiles = sens.get_stream_profiles();
1144 if (
profile.stream_type() == elem.first)
1155 if (!selected_profile)
1159 if (default_profile)
1162 selected_profile = default_profile;
1165 if(selected_profile)
1167 _fps[elem] = selected_profile.
fps();
1181 std::vector<std::string> filters_str;
1182 boost::split(filters_str,
_filters_str, [](
char c){
return c ==
',';});
1183 bool use_disparity_filter(
false);
1184 bool use_colorizer_filter(
false);
1185 bool use_decimation_filter(
false);
1186 bool use_hdr_filter(
false);
1187 for (std::vector<std::string>::const_iterator s_iter=filters_str.begin(); s_iter!=filters_str.end(); s_iter++)
1189 if ((*s_iter) ==
"colorizer")
1191 use_colorizer_filter =
true;
1193 else if ((*s_iter) ==
"disparity")
1195 use_disparity_filter =
true;
1197 else if ((*s_iter) ==
"spatial")
1202 else if ((*s_iter) ==
"temporal")
1207 else if ((*s_iter) ==
"hole_filling")
1209 ROS_INFO(
"Add Filter: hole_filling");
1210 _filters.push_back(
NamedFilter(
"hole_filling", std::make_shared<rs2::hole_filling_filter>()));
1212 else if ((*s_iter) ==
"decimation")
1214 use_decimation_filter =
true;
1216 else if ((*s_iter) ==
"pointcloud")
1220 else if ((*s_iter) ==
"hdr_merge")
1222 use_hdr_filter =
true;
1224 else if ((*s_iter).size() > 0)
1230 if (use_disparity_filter)
1234 _filters.push_back(
NamedFilter(
"disparity_end", std::make_shared<rs2::disparity_transform>(
false)));
1235 ROS_INFO(
"Done Add Filter: disparity");
1241 ROS_INFO(
"Add Filter: sequence_id_filter");
1244 if (use_decimation_filter)
1246 ROS_INFO(
"Add Filter: decimation");
1253 if (use_colorizer_filter)
1256 _colorizer = std::make_shared<rs2::colorizer>();
1270 ROS_INFO(
"Add Filter: pointcloud");
1279 static const float meter_to_mm = 0.001f;
1282 to_image = from_image;
1286 if (to_image.size() != from_image.size())
1288 to_image.create(from_image.rows, from_image.cols, from_image.type());
1293 int nRows = from_image.rows;
1294 int nCols = from_image.cols;
1296 if (from_image.isContinuous())
1305 for( i = 0; i < nRows; ++i)
1307 p_from = from_image.ptr<
uint16_t>(i);
1309 for ( j = 0; j < nCols; ++j)
1326 #pragma omp parallel for schedule(dynamic) //Using OpenMP to try to parallelise the loop 1328 for (
int y = 0;
y < height;
y++)
1330 auto depth_pixel_index =
y * width;
1331 for (
int x = 0;
x < width;
x++, ++depth_pixel_index)
1334 if (p_depth_frame[depth_pixel_index] > clipping_value)
1336 p_depth_frame[depth_pixel_index] = 0;
1359 template <
typename T>
T lerp(
const T &
a,
const T &
b,
const double t) {
1360 return a * (1.0 - t) + b * t;
1365 static std::deque<CimuData> _imu_history;
1366 _imu_history.push_back(imu_data);
1370 if ((type !=
ACCEL) || _imu_history.size() < 3)
1373 std::deque<CimuData> gyros_data;
1376 while (_imu_history.size())
1378 crnt_imu = _imu_history.front();
1379 _imu_history.pop_front();
1389 while (gyros_data.size())
1391 CimuData crnt_gyro = gyros_data.front();
1392 gyros_data.pop_front();
1401 gyros_data.push_back(crnt_imu);
1404 _imu_history.push_back(crnt_imu);
1415 _accel_data = imu_data;
1418 if (_accel_data.
m_time < 0)
1439 static std::mutex m_mutex;
1448 bool placeholder_false(
false);
1458 auto crnt_reading = *(
reinterpret_cast<const float3*
>(frame.
get_data()));
1459 Eigen::Vector3d
v(crnt_reading.x, crnt_reading.y, crnt_reading.z);
1461 std::deque<sensor_msgs::Imu> imu_msgs;
1462 switch (sync_method)
1472 while (imu_msgs.size())
1479 imu_msgs.pop_front();
1489 bool placeholder_false(
false);
1495 ROS_DEBUG(
"Frame arrived: stream: %s ; index: %d ; Timestamp Domain: %s",
1509 auto crnt_reading = *(
reinterpret_cast<const float3*
>(frame.
get_data()));
1510 if (
GYRO == stream_index)
1512 imu_msg.angular_velocity.x = crnt_reading.x;
1513 imu_msg.angular_velocity.y = crnt_reading.y;
1514 imu_msg.angular_velocity.z = crnt_reading.z;
1516 else if (
ACCEL == stream_index)
1518 imu_msg.linear_acceleration.x = crnt_reading.x;
1519 imu_msg.linear_acceleration.y = crnt_reading.y;
1520 imu_msg.linear_acceleration.z = crnt_reading.z;
1522 _seq[stream_index] += 1;
1523 imu_msg.header.seq =
_seq[stream_index];
1524 imu_msg.header.stamp = t;
1533 bool placeholder_false(
false);
1539 ROS_DEBUG(
"Frame arrived: stream: %s ; index: %d ; Timestamp Domain: %s",
1543 const auto& stream_index(
POSE);
1595 nav_msgs::Odometry odom_msg;
1596 _seq[stream_index] += 1;
1600 odom_msg.header.stamp = t;
1601 odom_msg.header.seq =
_seq[stream_index];
1602 odom_msg.pose.pose = pose_msg.
pose;
1603 odom_msg.pose.covariance = {cov_pose, 0, 0, 0, 0, 0,
1604 0, cov_pose, 0, 0, 0, 0,
1605 0, 0, cov_pose, 0, 0, 0,
1606 0, 0, 0, cov_twist, 0, 0,
1607 0, 0, 0, 0, cov_twist, 0,
1608 0, 0, 0, 0, 0, cov_twist};
1609 odom_msg.twist.twist.linear = v_msg.
vector;
1610 odom_msg.twist.twist.angular = om_msg.
vector;
1611 odom_msg.twist.covariance ={cov_pose, 0, 0, 0, 0, 0,
1612 0, cov_pose, 0, 0, 0, 0,
1613 0, 0, cov_pose, 0, 0, 0,
1614 0, 0, 0, cov_twist, 0, 0,
1615 0, 0, 0, 0, cov_twist, 0,
1616 0, 0, 0, 0, 0, cov_twist};
1632 bool placeholder_false(
false);
1643 ROS_DEBUG(
"List of frameset before applying filters: size: %d", static_cast<int>(frameset.size()));
1644 for (
auto it = frameset.begin(); it != frameset.end(); ++it)
1647 auto stream_type =
f.get_profile().stream_type();
1648 auto stream_index =
f.get_profile().stream_index();
1650 auto stream_unique_id =
f.get_profile().unique_id();
1652 ROS_DEBUG(
"Frameset contain (%s, %d, %s %d) frame. frame_number: %llu ; frame_TS: %f ; ros_TS(NSec): %lu",
1658 bool is_color_frame(frameset.get_color_frame());
1664 ROS_DEBUG(
"num_filters: %d", static_cast<int>(
_filters.size()));
1665 for (std::vector<NamedFilter>::const_iterator filter_it =
_filters.begin(); filter_it !=
_filters.end(); filter_it++)
1667 ROS_DEBUG(
"Applying filter: %s", filter_it->_name.c_str());
1668 if ((filter_it->_name ==
"pointcloud") && (!original_depth_frame))
1670 if ((filter_it->_name ==
"align_to_color") && (!is_color_frame))
1672 frameset = filter_it->_filter->process(frameset);
1675 ROS_DEBUG(
"List of frameset after applying filters: size: %d", static_cast<int>(frameset.size()));
1676 bool sent_depth_frame(
false);
1677 for (
auto it = frameset.begin(); it != frameset.end(); ++it)
1680 auto stream_type =
f.get_profile().stream_type();
1681 auto stream_index =
f.get_profile().stream_index();
1685 ROS_DEBUG(
"Frameset contain (%s, %d, %s) frame. frame_number: %llu ; frame_TS: %f ; ros_TS(NSec): %lu",
1697 if (sent_depth_frame)
continue;
1698 sent_depth_frame =
true;
1722 frame_to_send =
_colorizer->process(original_depth_frame);
1724 frame_to_send = original_depth_frame;
1739 ROS_DEBUG(
"Single video frame arrived (%s, %d). frame_number: %llu ; frame_TS: %f ; ros_TS(NSec): %lu",
1760 catch(
const std::exception& ex)
1762 ROS_ERROR_STREAM(
"An error has occurred during frame callback: " << ex.what());
1790 ROS_WARN(
"frame's time domain is HARDWARE_CLOCK. Timestamps may reset periodically.");
1829 std::map<std::string, std::vector<rs2::stream_profile> >
profiles;
1830 std::map<std::string, rs2::sensor> active_sensors;
1835 <<
" to " << module_name);
1836 profiles[module_name].insert(profiles[module_name].
begin(),
1842 for (
const std::pair<std::string, std::vector<rs2::stream_profile> >& sensor_profile : profiles)
1844 std::string module_name = sensor_profile.first;
1846 sensor.
open(sensor_profile.second);
1854 catch(
const std::exception& ex)
1895 if (stream_index.second == 2)
1902 _camera_info[stream_index].P.at(3) = -intrinsic.fx * ex.translation[0] + 0.0;
1903 _camera_info[stream_index].P.at(7) = -intrinsic.fy * ex.translation[1] + 0.0;
1909 _camera_info[stream_index].distortion_model =
"equidistant";
1911 _camera_info[stream_index].distortion_model =
"plumb_bob";
1926 for (
int i = 0;
i < 5;
i++)
1956 m << rotation[0], rotation[3], rotation[6],
1957 rotation[1], rotation[4], rotation[7],
1958 rotation[2], rotation[5], rotation[8];
1959 Eigen::Quaternionf
q(m);
1966 const std::string& from,
1967 const std::string& to)
1987 quaternion_optical.
setRPY(-M_PI / 2, 0.0, -M_PI / 2);
1988 float3 zero_trans{0, 0, 0};
1997 catch (std::exception&
e)
1999 if (!strcmp(e.what(),
"Requested extrinsics are not available!"))
2002 ex =
rs2_extrinsics({{1, 0, 0, 0, 1, 0, 0, 0, 1}, {0,0,0}});
2011 Q = quaternion_optical *
Q * quaternion_optical.
inverse();
2028 const std::vector<stream_index_pair> base_stream_priority = {
DEPTH,
POSE};
2030 std::vector<stream_index_pair>::const_iterator base_stream(base_stream_priority.begin());
2031 while( (
_sensors.find(*base_stream) ==
_sensors.end()) && (base_stream != base_stream_priority.end()))
2035 if (base_stream == base_stream_priority.end())
2037 throw std::runtime_error(
"No known base_stream found for transformations.");
2039 ROS_INFO_STREAM(
"SELECTED BASE:" << base_stream->first <<
", " << base_stream->second);
2051 for (std::pair<stream_index_pair, bool> ienable :
_enable)
2069 static const char* frame_id =
"depth_to_fisheye_extrinsics";
2079 static const char* frame_id =
"depth_to_color_extrinsics";
2088 static const char* frame_id =
"depth_to_infra1_extrinsics";
2097 static const char* frame_id =
"depth_to_infra2_extrinsics";
2111 std::unique_lock<std::mutex> lock(mu);
2118 msg.header.stamp = t;
2145 for (i=0; i < n; ++i)
2146 dst[n-1-i] = src[i];
2158 static int warn_count(0);
2159 static const int DISPLAY_WARN_NUMBER(5);
2163 std::set<rs2_format> available_formats{ rs2_format::RS2_FORMAT_RGB8, rs2_format::RS2_FORMAT_Y8 };
2165 texture_frame_itr = find_if(frameset.
begin(), frameset.
end(), [&texture_source_id, &available_formats] (
rs2::frame f)
2166 {
return (
rs2_stream(
f.get_profile().stream_type()) == texture_source_id) &&
2167 (available_formats.find(
f.get_profile().format()) != available_formats.end()); });
2168 if (texture_frame_itr == frameset.
end())
2171 std::string texture_source_name =
_pointcloud_filter->get_option_value_description(rs2_option::RS2_OPTION_STREAM_FILTER, static_cast<float>(texture_source_id));
2172 ROS_WARN_STREAM_COND(warn_count == DISPLAY_WARN_NUMBER,
"No stream match for pointcloud chosen texture " << texture_source_name);
2178 int texture_width(0), texture_height(0);
2197 size_t valid_count(0);
2201 texture_width = texture_frame.
get_width();
2205 std::string format_str;
2212 format_str =
"intensity";
2227 float color_pixel[2];
2228 for (
size_t point_idx=0; point_idx < pc.
size(); point_idx++, vertex++, color_point++)
2230 float i(color_point->
u);
2231 float j(color_point->
v);
2232 bool valid_color_pixel(i >= 0.
f && i <=1.f && j >= 0.
f && j <=1.
f);
2236 *iter_x = vertex->x;
2237 *iter_y = vertex->y;
2238 *iter_z = vertex->z;
2240 if (valid_color_pixel)
2242 color_pixel[0] = i * texture_width;
2243 color_pixel[1] = j * texture_height;
2244 int pixx =
static_cast<int>(color_pixel[0]);
2245 int pixy =
static_cast<int>(color_pixel[1]);
2246 int offset = (pixy * texture_width + pixx) * num_colors;
2249 ++iter_x; ++iter_y; ++iter_z;
2257 std::string format_str =
"intensity";
2265 for (
size_t point_idx=0; point_idx < pc.
size(); point_idx++, vertex++)
2267 bool valid_pixel(vertex->
z > 0);
2270 *iter_x = vertex->
x;
2271 *iter_y = vertex->
y;
2272 *iter_z = vertex->
z;
2274 ++iter_x; ++iter_y; ++iter_z;
2287 modifier.
resize(valid_count);
2295 Extrinsics extrinsicsMsg;
2296 for (
int i = 0;
i < 9; ++
i)
2298 extrinsicsMsg.rotation[
i] = extrinsics.
rotation[
i];
2303 extrinsicsMsg.header.frame_id = frame_id;
2304 return extrinsicsMsg;
2309 const std::vector<rs2::stream_profile>
profiles =
_sensors[stream].get_stream_profiles();
2310 return *(std::find_if(profiles.begin(), profiles.end(),
2312 return ((
profile.stream_type() == stream.first) && (
profile.stream_index() == stream.second));
2323 imuIntrinsics = sp.get_motion_intrinsics();
2325 catch(
const std::runtime_error &ex)
2328 imuIntrinsics = {{{1,0,0,0},{0,1,0,0},{0,0,1,0}}, {0,0,0}, {0,0,0}};
2333 for (
int i = 0;
i < 3; ++
i)
2335 for (
int j = 0;
j < 4; ++
j)
2340 info.noise_variances[
i] = imuIntrinsics.noise_variances[
i];
2341 info.bias_variances[
i] = imuIntrinsics.bias_variances[
i];
2348 std::map<stream_index_pair, cv::Mat>& images,
2349 const std::map<stream_index_pair, ros::Publisher>& info_publishers,
2350 const std::map<stream_index_pair, ImagePublisherWithFrequencyDiagnostics>& image_publishers,
2351 std::map<stream_index_pair, int>&
seq,
2352 std::map<stream_index_pair, sensor_msgs::CameraInfo>& camera_info,
2353 const std::map<rs2_stream, std::string>& encoding,
2354 bool copy_data_from_frame)
2357 unsigned int width = 0;
2364 height =
image.get_height();
2367 auto&
image = images[stream];
2369 if (copy_data_from_frame)
2371 if (images[stream].
size() != cv::Size(width, height))
2383 auto& info_publisher = info_publishers.at(stream);
2384 auto& image_publisher = image_publishers.at(stream);
2386 image_publisher.second->tick();
2387 if(0 != info_publisher.getNumSubscribers() ||
2388 0 != image_publisher.first.getNumSubscribers())
2390 auto& cam_info = camera_info.at(stream);
2391 if (cam_info.width != width)
2395 cam_info.header.stamp = t;
2396 cam_info.header.seq = seq[stream];
2397 info_publisher.publish(cam_info);
2402 img->height = height;
2403 img->is_bigendian =
false;
2404 img->step = width *
bpp;
2405 img->header.frame_id = cam_info.header.frame_id;
2406 img->header.stamp = t;
2407 img->header.seq = seq[stream];
2409 image_publisher.first.publish(img);
2421 {
return (profile.
stream_type() == stream_index.first); });
2436 int time_interval(1000);
2437 std::function<void()>
func = [
this, time_interval](){
2439 std::unique_lock<std::mutex> lock(mu);
2462 auto option_value = sensor.
get_option(option);
2463 option_diag.second->update(option_value);
2465 catch(
const std::exception&
e)
2467 ROS_DEBUG_STREAM(
"Failed checking for temperature." << std::endl << e.what());
2477 image_publisher.second.second->update();
2484 _updater.setHardwareID(serial_no);
2490 status.
add(
"Index", _crnt_temp);
std::map< stream_index_pair, cv::Mat > _depth_aligned_image
void FillImuData_Copy(const CimuData imu_data, std::deque< sensor_msgs::Imu > &imu_msgs)
std::map< stream_index_pair, int > _seq
RS2_OPTION_PROJECTOR_TEMPERATURE
std::map< rs2_stream, int > _image_format
BaseRealSenseNode(ros::NodeHandle &nodeHandle, ros::NodeHandle &privateNodeHandle, rs2::device dev, const std::string &serial_no)
void monitor_update_functions()
const std::vector< stream_index_pair > IMAGE_STREAMS
GLboolean GLboolean GLboolean b
const std::string DEFAULT_BASE_FRAME_ID
void clip_depth(rs2::depth_frame depth_frame, float clipping_dist)
cv::Mat & fix_depth_scale(const cv::Mat &from_image, cv::Mat &to_image)
void registerAutoExposureROIOptions(ros::NodeHandle &nh)
TemperatureDiagnostics(std::string name, std::string serial_no)
tf2_ros::StaticTransformBroadcaster _static_tf_broadcaster
RS2_CAMERA_INFO_PHYSICAL_PORT
std::vector< sensor > query_sensors() const
tf::Quaternion rotationMatrixToQuaternion(const float rotation[9]) const
_linear_acceleration_type linear_acceleration
const std::string DEFAULT_ODOM_FRAME_ID
void publish(const boost::shared_ptr< M > &message) const
void ImuMessage_AddDefaultValues(sensor_msgs::Imu &imu_msg)
unsigned int tracker_confidence
std::vector< NamedFilter > _filters
const std::string DEFAULT_IMU_OPTICAL_FRAME_ID
RS2_TIMESTAMP_DOMAIN_HARDWARE_CLOCK
ros::Publisher _publisher
void publishPointCloud(rs2::points f, const ros::Time &t, const rs2::frameset &frameset)
std::map< stream_index_pair, ros::Publisher > _info_publisher
void pose_callback(rs2::frame frame)
tf2_ros::TransformBroadcaster _dynamic_tf_broadcaster
void summary(unsigned char lvl, const std::string s)
std::map< stream_index_pair, rs2_intrinsics > _stream_intrinsics
const bool PUBLISH_ODOM_TF
RS2_CAMERA_INFO_PRODUCT_ID
void reverse_memcpy(unsigned char *dst, const unsigned char *src, size_t n)
rs2_extrinsics get_extrinsics_to(const stream_profile &to) const
std::condition_variable _cv_tf
bool deleteParam(const std::string &key) const
std::string resolveName(const std::string &name, bool remap=true) const
double frameSystemTimeSec(rs2::frame frame)
stream_profile get_profile() const
rs2_log_severity get_severity() const
bool call(const std::string &service_name, MReq &req, MRes &res)
void set_sensor_parameter_to_ros(const std::string &module_name, rs2::options sensor, rs2_option option)
double _angular_velocity_cov
const std::string DEFAULT_UNITE_IMU_METHOD
#define OPTICAL_FRAME_ID(sip)
std::size_t _waiting_list_size
_orientation_type orientation
int get_bytes_per_pixel() const
virtual void registerDynamicReconfigCb(ros::NodeHandle &nh) override
std::string _base_frame_id
Publisher advertise(const std::string &base_topic, uint32_t queue_size, bool latch=false)
RS2_DISTORTION_KANNALA_BRANDT4
RS2_OPTION_ASIC_TEMPERATURE
ros::Publisher _pointcloud_publisher
const void * get_data() const
_angular_velocity_covariance_type angular_velocity_covariance
struct Vertex vertex[VERTEXNUM]
virtual void publishTopics() override
std::shared_ptr< rs2::filter > _pointcloud_filter
Extrinsics rsExtrinsicsToMsg(const rs2_extrinsics &extrinsics, const std::string &frame_id) const
const stream_index_pair INFRA2
std::string get_description() const
static void vector3TFToMsg(const Vector3 &bt_v, geometry_msgs::Vector3 &msg_v)
virtual void toggleSensors(bool enabled) override
_orientation_type orientation
std::shared_ptr< std::thread > _update_functions_t
IMUInfo getImuInfo(const stream_index_pair &stream_index)
stream_index_pair _pointcloud_texture
std::map< rs2_stream, bool > _is_first_frame
const char * rs2_stream_to_string(rs2_stream stream)
void publishFrame(rs2::frame f, const ros::Time &t, const stream_index_pair &stream, std::map< stream_index_pair, cv::Mat > &images, const std::map< stream_index_pair, ros::Publisher > &info_publishers, const std::map< stream_index_pair, ImagePublisherWithFrequencyDiagnostics > &image_publishers, std::map< stream_index_pair, int > &seq, std::map< stream_index_pair, sensor_msgs::CameraInfo > &camera_info, const std::map< rs2_stream, std::string > &encoding, bool copy_data_from_frame=true)
rs2_vector angular_velocity
std::map< stream_index_pair, ImagePublisherWithFrequencyDiagnostics > _image_publishers
TFSIMD_FORCE_INLINE const tfScalar & getW() const
std::atomic_bool _is_initialized_time_base
const texture_coordinate * get_texture_coordinates() const
void registerDynamicOption(ros::NodeHandle &nh, rs2::options sensor, std::string &module_name)
void publishStaticTransforms()
GLenum GLenum GLsizei void * image
void imu_callback_sync(rs2::frame frame, imu_sync_method sync_method=imu_sync_method::COPY)
std::queue< sensor_msgs::Imu > _pending_messages
std::pair< rs2_option, std::shared_ptr< TemperatureDiagnostics > > OptionTemperatureDiag
std::map< stream_index_pair, sensor_msgs::CameraInfo > _depth_aligned_camera_info
virtual ~BaseRealSenseNode()
std::vector< OptionTemperatureDiag > _temperature_nodes
GLboolean GLboolean GLboolean GLboolean a
void Publish(sensor_msgs::Imu msg)
std::map< stream_index_pair, rs2::sensor > _sensors
std::map< stream_index_pair, int > _width
bool is_checkbox(rs2::options sensor, rs2_option option)
std::pair< rs2_stream, int > stream_index_pair
void updateStreamCalibData(const rs2::video_stream_profile &video_profile)
std::map< std::string, int > get_enum_method(rs2::options sensor, rs2_option option)
GLfloat GLfloat GLfloat alpha
const stream_index_pair CONFIDENCE
sensor_msgs::PointCloud2 _msg_pointcloud
std::condition_variable _cv_monitoring
bool is_enum_option(rs2::options sensor, rs2_option option)
T lerp(const T &a, const T &b, const double t)
void load_json(const std::string &json_content) const
std::shared_ptr< rs2::filter > _colorizer
const char * rs2_option_to_string(rs2_option option)
void publishDynamicTransforms()
std::map< stream_index_pair, rs2_extrinsics > _depth_to_other_extrinsics
float _depth_scale_meters
const char * get_option_description(rs2_option option) const
std::map< rs2_stream, std::string > _encoding
static void vector3MsgToTF(const geometry_msgs::Vector3 &msg_v, Vector3 &bt_v)
ROSCPP_DECL const std::string & getNamespace()
double get_timestamp() const
_point_step_type point_step
std::map< stream_index_pair, bool > _enable
const stream_index_pair GYRO
std::map< stream_index_pair, cv::Mat > _image
const char * get_info(rs2_camera_info info) const
void frame_callback(rs2::frame frame)
void setRPY(const tfScalar &roll, const tfScalar &pitch, const tfScalar &yaw)
std::shared_ptr< std::thread > _tf_t
bool is_option_read_only(rs2_option option) const
GLint GLsizei GLsizei height
#define ROS_WARN_ONCE(...)
bool _allow_no_texture_points
std::map< rs2_stream, std::vector< std::function< void()> > > _video_functions_stack
const stream_index_pair DEPTH
const vertex * get_vertices() const
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
void publish_frequency_update()
std::shared_ptr< SyncedImuPublisher > _synced_imu_publisher
const char * rs2_format_to_string(rs2_format format)
std::string create_graph_resource_name(const std::string &original_name)
ros::NodeHandle & _node_handle
GLenum GLenum GLsizei const GLuint GLboolean enabled
const std::string TYPE_16UC1
float get_depth_scale(rs2::device dev)
std::map< rs2_stream, std::string > _stream_name
#define ROS_WARN_STREAM_COND(cond, args)
RS2_CAMERA_INFO_FIRMWARE_VERSION
TFSIMD_FORCE_INLINE Vector3 quatRotate(const Quaternion &rotation, const Vector3 &v)
void imu_callback(rs2::frame frame)
std::map< stream_index_pair, ImagePublisherWithFrequencyDiagnostics > _depth_aligned_image_publishers
std::map< stream_index_pair, cv::Mat > _depth_scaled_image
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void multiple_message_callback(rs2::frame frame, imu_sync_method sync_method)
bool supports(rs2_option option) const
rs2_stream rs2_string_to_stream(std::string str)
rs2_intrinsics get_intrinsics() const
#define ROS_WARN_STREAM(args)
#define ROS_DEBUG_STREAM(args)
rs2_notification_category get_category() const
const bool ALLOW_NO_TEXTURE_POINTS
void publish_temperature()
imu_sync_method _imu_sync_method
Quaternion inverse() const
bool getEnabledProfile(const stream_index_pair &stream_index, rs2::stream_profile &profile)
void registerHDRoptions()
rs2_format format() const
_angular_velocity_type angular_velocity
std::map< stream_index_pair, std::vector< rs2::stream_profile > > _enabled_profiles
#define ROS_INFO_STREAM_ONCE(args)
GLdouble GLdouble GLdouble q
const std::string _namespace
std::map< stream_index_pair, ros::Publisher > _imu_publishers
virtual void calcAndPublishStaticTransform(const stream_index_pair &stream, const rs2::stream_profile &base_profile)
uint32_t getNumSubscribers() const
void diagnostics(diagnostic_updater::DiagnosticStatusWrapper &status)
#define ROS_INFO_STREAM(args)
std::map< stream_index_pair, ros::Publisher > _depth_to_other_extrinsics_publishers
std::vector< rs2_option > _monitor_options
std::vector< std::function< void()> > _update_functions_v
std::map< stream_index_pair, std::string > _frame_id
rs2_timestamp_domain get_frame_timestamp_domain() const
std::map< stream_index_pair, int > _height
const stream_index_pair ACCEL
const stream_index_pair POSE
void set_sensor_auto_exposure_roi(rs2::sensor sensor)
std::map< stream_index_pair, sensor_msgs::CameraInfo > _camera_info
_orientation_covariance_type orientation_covariance
void readAndSetDynamicParam(ros::NodeHandle &nh1, std::shared_ptr< ddynamic_reconfigure::DDynamicReconfigure > ddynrec, const std::string option_name, const int min_val, const int max_val, rs2::sensor sensor, int *option_value)
std::map< rs2_stream, int > _unit_step_size
const double TF_PUBLISH_RATE
std::shared_ptr< std::thread > _monitoring_t
void publish_static_tf(const ros::Time &t, const float3 &trans, const tf::Quaternion &q, const std::string &from, const std::string &to)
void open(const stream_profile &profile) const
_linear_acceleration_covariance_type linear_acceleration_covariance
std::vector< geometry_msgs::TransformStamped > _static_tf_msgs
const bool ORDERED_POINTCLOUD
double get_timestamp() const
std::map< rs2_stream, std::string > _depth_aligned_encoding
void setupErrorCallback()
ROSCPP_DECL void shutdown()
const std::vector< stream_index_pair > HID_STREAMS
std::map< stream_index_pair, int > _fps
static std::string getNamespaceStr()
const bool HOLD_BACK_IMU_FOR_FRAMES
std::map< std::string, std::function< void(rs2::frame)> > _sensors_callback
stream_index_pair _base_stream
std::vector< rs2::sensor > _dev_sensors
void runFirstFrameInitialization(rs2_stream stream_type)
std::vector< std::shared_ptr< ddynamic_reconfigure::DDynamicReconfigure > > _ddynrec
void add(const std::string &key, const T &val)
std::map< stream_index_pair, int > _depth_aligned_seq
option_range get_option_range(rs2_option option) const
const stream_index_pair FISHEYE
std::condition_variable _update_functions_cv
const char * get_info(rs2_camera_info info) const
const stream_index_pair COLOR
void PublishPendingMessages()
#define ROS_ERROR_STREAM(args)
std::map< std::string, rs2::region_of_interest > _auto_exposure_roi
bool isValidCharInName(char c)
sensor_msgs::Imu CreateUnitedMessage(const CimuData accel_data, const CimuData gyro_data)
const stream_index_pair INFRA1
bool setBaseTime(double frame_time, rs2_timestamp_domain time_domain)
rs2::stream_profile getAProfile(const stream_index_pair &stream)
std::string _json_file_path
void setPointCloud2FieldsByString(int n_fields,...)
const char * rs2_timestamp_domain_to_string(rs2_timestamp_domain info)
unsigned long long get_frame_number() const
::sensor_msgs::Imu_< std::allocator< void > > Imu
rs2_stream stream_type() const
std::map< stream_index_pair, ros::Publisher > _depth_aligned_info_publisher
std::map< stream_index_pair, std::string > _optical_frame_id
void set_option(rs2_option option, float value) const
#define ALIGNED_DEPTH_TO_FRAME_ID(sip)
bool _hold_back_imu_for_frames
float get_option(rs2_option option) const
const float ROS_DEPTH_SCALE
bool is_int_option(rs2::options sensor, rs2_option option)
std::string _odom_frame_id
const char * get_option_value_description(rs2_option option, float val) const
RS2_TIMESTAMP_DOMAIN_SYSTEM_TIME
void set_auto_exposure_roi(const std::string option_name, rs2::sensor sensor, int new_value)
void start(T callback) const
const std::string DEFAULT_FILTERS
std::map< stream_index_pair, std::string > _depth_aligned_frame_id
void FillImuData_LinearInterpolation(const CimuData imu_data, std::deque< sensor_msgs::Imu > &imu_msgs)
std::shared_ptr< ::sensor_msgs::Image > ImagePtr
std::map< rs2_stream, int > _format
std::string to_string(T value)