34 #include <arpa/inet.h> 36 #include <turbojpeg.h> 38 #include <Eigen/Geometry> 39 #include <opencv2/opencv.hpp> 46 #include <multisense_lib/MultiSenseChannel.hh> 48 #include <multisense_ros/RawCamConfig.h> 49 #include <multisense_ros/RawCamCal.h> 50 #include <multisense_ros/DeviceInfo.h> 51 #include <multisense_ros/Histogram.h> 94 {
reinterpret_cast<Camera*
>(userDataP)->monoCallback(header); }
96 {
reinterpret_cast<Camera*
>(userDataP)->rectCallback(header); }
98 {
reinterpret_cast<Camera*
>(userDataP)->depthCallback(header); }
100 {
reinterpret_cast<Camera*
>(userDataP)->pointCloudCallback(header); }
102 {
reinterpret_cast<Camera*
>(userDataP)->rawCamDataCallback(header); }
104 {
reinterpret_cast<Camera*
>(userDataP)->colorImageCallback(header); }
106 {
reinterpret_cast<Camera*
>(userDataP)->disparityImageCallback(header); }
108 {
reinterpret_cast<Camera*
>(userDataP)->jpegImageCallback(header); }
110 {
reinterpret_cast<Camera*
>(userDataP)->histogramCallback(header); }
111 void colorizeCB(
const image::Header& header,
void* userDataP)
112 {
reinterpret_cast<Camera*
>(userDataP)->colorizeCallback(header); }
113 void groundSurfaceCB(
const image::Header& header,
void* userDataP)
114 {
reinterpret_cast<Camera*
>(userDataP)->groundSurfaceCallback(header); }
116 {
reinterpret_cast<Camera*
>(userDataP)->groundSurfaceSplineCallback(header); }
119 bool isValidReprojectedPoint(
const Eigen::Vector3f& pt,
float squared_max_range)
121 return pt[2] > 0.0f && std::isfinite(pt[2]) && pt.squaredNorm() < squared_max_range;
124 void writePoint(sensor_msgs::PointCloud2 &pointcloud,
size_t index,
const Eigen::Vector3f &point, uint32_t color)
126 float* cloudP =
reinterpret_cast<float*
>(&(pointcloud.data[index * pointcloud.point_step]));
127 cloudP[0] = point[0];
128 cloudP[1] = point[1];
129 cloudP[2] = point[2];
131 uint32_t* colorP =
reinterpret_cast<uint32_t*
>(&(cloudP[3]));
135 void writePoint(sensor_msgs::PointCloud2 &pointcloud,
136 size_t pointcloud_index,
137 const Eigen::Vector3f &point,
145 const uint32_t luma =
static_cast<uint32_t
>(
reinterpret_cast<const uint8_t*
>(image.
imageDataP)[image_index]);
146 return writePoint(pointcloud, pointcloud_index, point, luma);
150 const uint32_t luma =
static_cast<uint32_t
>(
reinterpret_cast<const uint16_t*
>(image.
imageDataP)[image_index]);
151 return writePoint(pointcloud, pointcloud_index, point, luma);
155 const uint32_t luma =
reinterpret_cast<const uint32_t*
>(image.
imageDataP)[image_index];
156 return writePoint(pointcloud, pointcloud_index, point, luma);
161 bool clipPoint(
const BorderClip& borderClipType,
162 double borderClipValue,
168 switch (borderClipType)
170 case BorderClip::NONE:
174 case BorderClip::RECTANGULAR:
176 return !( u >= borderClipValue && u <= width - borderClipValue &&
177 v >= borderClipValue && v <= height - borderClipValue);
179 case BorderClip::CIRCULAR:
181 const double halfWidth =
static_cast<double>(width)/2.0;
182 const double halfHeight =
static_cast<double>(height)/2.0;
184 const double radius =
sqrt( halfWidth * halfWidth + halfHeight * halfHeight ) - borderClipValue;
186 return !(Eigen::Vector2d{halfWidth - u, halfHeight - v}.norm() < radius);
190 ROS_WARN(
"Camera: Unknown border clip type.");
198 cv::Vec3b interpolate_color(
const Eigen::Vector2f &pixel,
const cv::Mat &image)
200 const float width = image.cols;
201 const float height = image.rows;
203 const float &u = pixel(0);
204 const float &v = pixel(1);
210 const size_t min_u =
static_cast<size_t>(std::min(std::max(std::floor(u), 0.f), width - 1.f));
211 const size_t max_u =
static_cast<size_t>(std::min(std::max(std::floor(u) + 1, 0.f), width - 1.f));
212 const size_t min_v =
static_cast<size_t>(std::min(std::max(std::floor(v), 0.f), height - 1.f));
213 const size_t max_v =
static_cast<size_t>(std::min(std::max(std::floor(v) + 1, 0.f), height - 1.f));
215 const cv::Vec3d element00 = image.at<cv::Vec3b>(width * min_v + min_u);
216 const cv::Vec3d element01 = image.at<cv::Vec3b>(width * min_v + max_u);
217 const cv::Vec3d element10 = image.at<cv::Vec3b>(width * max_v + min_u);
218 const cv::Vec3d element11 = image.at<cv::Vec3b>(width * max_v + max_u);
220 const size_t delta_u = max_u - min_u;
221 const size_t delta_v = max_v - min_v;
223 const double u_ratio = delta_u == 0 ? 1. : (
static_cast<double>(max_u) - u) /
static_cast<double>(delta_u);
224 const double v_ratio = delta_v == 0 ? 1. : (
static_cast<double>(max_v) - v) /
static_cast<double>(delta_v);
226 const cv::Vec3b f_xy0 = element00 * u_ratio + element01 * (1. - u_ratio);
227 const cv::Vec3b f_xy1 = element10 * u_ratio + element11 * (1. - u_ratio);
229 return (f_xy0 * v_ratio + f_xy1 * (1. - v_ratio));
237 constexpr
char Camera::LEFT[];
238 constexpr
char Camera::RIGHT[];
239 constexpr
char Camera::AUX[];
240 constexpr
char Camera::CALIBRATION[];
241 constexpr
char Camera::GROUND_SURFACE[];
243 constexpr
char Camera::ORIGIN_FRAME[];
244 constexpr
char Camera::HEAD_FRAME[];
245 constexpr
char Camera::LEFT_CAMERA_FRAME[];
246 constexpr
char Camera::RIGHT_CAMERA_FRAME[];
247 constexpr
char Camera::LEFT_RECTIFIED_FRAME[];
248 constexpr
char Camera::RIGHT_RECTIFIED_FRAME[];
249 constexpr
char Camera::AUX_CAMERA_FRAME[];
250 constexpr
char Camera::AUX_RECTIFIED_FRAME[];
252 constexpr
char Camera::DEVICE_INFO_TOPIC[];
253 constexpr
char Camera::RAW_CAM_CAL_TOPIC[];
254 constexpr
char Camera::RAW_CAM_CONFIG_TOPIC[];
255 constexpr
char Camera::RAW_CAM_DATA_TOPIC[];
256 constexpr
char Camera::HISTOGRAM_TOPIC[];
257 constexpr
char Camera::MONO_TOPIC[];
258 constexpr
char Camera::RECT_TOPIC[];
259 constexpr
char Camera::DISPARITY_TOPIC[];
260 constexpr
char Camera::DISPARITY_IMAGE_TOPIC[];
261 constexpr
char Camera::DEPTH_TOPIC[];
262 constexpr
char Camera::OPENNI_DEPTH_TOPIC[];
263 constexpr
char Camera::COST_TOPIC[];
264 constexpr
char Camera::COLOR_TOPIC[];
265 constexpr
char Camera::RECT_COLOR_TOPIC[];
266 constexpr
char Camera::POINTCLOUD_TOPIC[];
267 constexpr
char Camera::COLOR_POINTCLOUD_TOPIC[];
268 constexpr
char Camera::ORGANIZED_POINTCLOUD_TOPIC[];
269 constexpr
char Camera::COLOR_ORGANIZED_POINTCLOUD_TOPIC[];
270 constexpr
char Camera::MONO_CAMERA_INFO_TOPIC[];
271 constexpr
char Camera::RECT_CAMERA_INFO_TOPIC[];
272 constexpr
char Camera::COLOR_CAMERA_INFO_TOPIC[];
273 constexpr
char Camera::RECT_COLOR_CAMERA_INFO_TOPIC[];
274 constexpr
char Camera::DEPTH_CAMERA_INFO_TOPIC[];
275 constexpr
char Camera::DISPARITY_CAMERA_INFO_TOPIC[];
276 constexpr
char Camera::COST_CAMERA_INFO_TOPIC[];
277 constexpr
char Camera::GROUND_SURFACE_IMAGE_TOPIC[];
278 constexpr
char Camera::GROUND_SURFACE_INFO_TOPIC[];
279 constexpr
char Camera::GROUND_SURFACE_POINT_SPLINE_TOPIC[];
281 Camera::Camera(
Channel* driver,
const std::string& tf_prefix) :
284 left_nh_(device_nh_, LEFT),
285 right_nh_(device_nh_, RIGHT),
286 aux_nh_(device_nh_, AUX),
287 calibration_nh_(device_nh_, CALIBRATION),
288 ground_surface_nh_(device_nh_, GROUND_SURFACE),
289 left_mono_transport_(left_nh_),
290 right_mono_transport_(right_nh_),
291 left_rect_transport_(left_nh_),
292 right_rect_transport_(right_nh_),
293 left_rgb_transport_(left_nh_),
294 left_rgb_rect_transport_(left_nh_),
295 depth_transport_(device_nh_),
296 ni_depth_transport_(device_nh_),
297 disparity_left_transport_(left_nh_),
298 disparity_right_transport_(right_nh_),
299 disparity_cost_transport_(left_nh_),
300 aux_mono_transport_(aux_nh_),
301 aux_rgb_transport_(aux_nh_),
302 aux_rect_transport_(aux_nh_),
303 aux_rgb_rect_transport_(aux_nh_),
304 ground_surface_transport_(ground_surface_nh_),
305 stereo_calibration_manager_(nullptr),
306 frame_id_origin_(tf_prefix + ORIGIN_FRAME),
307 frame_id_head_(tf_prefix + HEAD_FRAME),
308 frame_id_left_(tf_prefix + LEFT_CAMERA_FRAME),
309 frame_id_right_(tf_prefix + RIGHT_CAMERA_FRAME),
310 frame_id_aux_(tf_prefix + AUX_CAMERA_FRAME),
311 frame_id_rectified_left_(tf_prefix + LEFT_RECTIFIED_FRAME),
312 frame_id_rectified_right_(tf_prefix + RIGHT_RECTIFIED_FRAME),
313 frame_id_rectified_aux_(tf_prefix + AUX_RECTIFIED_FRAME),
314 static_tf_broadcaster_(),
315 pointcloud_max_range_(15.0),
318 border_clip_value_(0.0)
324 if (Status_Ok != status) {
325 ROS_ERROR(
"Camera: failed to query version info: %s", Channel::statusString(status));
330 if (Status_Ok != status) {
331 ROS_ERROR(
"Camera: failed to query device info: %s", Channel::statusString(status));
340 if (Status_Ok != status) {
341 ROS_ERROR(
"Camera: failed to query sensor configuration: %s", Channel::statusString(status));
401 if (can_support_ground_surface_) {
525 const auto point_cloud_color_topics =
has_aux_camera_ ? Source_Luma_Rectified_Aux | Source_Chroma_Rectified_Aux :
526 Source_Luma_Left | Source_Chroma_Left;
530 Source_Disparity | point_cloud_color_topics),
532 Source_Disparity | point_cloud_color_topics));
536 Source_Disparity | point_cloud_color_topics),
538 Source_Disparity | point_cloud_color_topics));
596 multisense_ros::DeviceInfo
msg;
605 msg.pcbSerialNumbers.push_back(pcb.revision);
606 msg.pcbNames.push_back(pcb.name);
647 if (Status_Ok != status) {
648 ROS_ERROR(
"Camera: failed to query image calibration: %s",
649 Channel::statusString(status));
655 multisense_ros::RawCamCal cal;
658 cP =
reinterpret_cast<const float *
>(&(image_calibration.
left.
M[0][0]));
659 for(uint32_t i=0; i<9; i++) cal.left_M[i] = cP[i];
660 cP = reinterpret_cast<const float *>(&(image_calibration.
left.
D[0]));
661 for(uint32_t i=0; i<8; i++) cal.left_D[i] = cP[i];
662 cP = reinterpret_cast<const float *>(&(image_calibration.
left.
R[0][0]));
663 for(uint32_t i=0; i<9; i++) cal.left_R[i] = cP[i];
664 cP = reinterpret_cast<const float *>(&(image_calibration.
left.
P[0][0]));
665 for(uint32_t i=0; i<12; i++) cal.left_P[i] = cP[i];
670 cP =
reinterpret_cast<const float *
>(&(image_calibration.
left.
M[0][0]));
671 for(uint32_t i=0; i<9; i++) cal.right_M[i] = cP[i];
672 cP = reinterpret_cast<const float *>(&(image_calibration.
left.
D[0]));
673 for(uint32_t i=0; i<8; i++) cal.right_D[i] = cP[i];
674 cP = reinterpret_cast<const float *>(&(image_calibration.
left.
R[0][0]));
675 for(uint32_t i=0; i<9; i++) cal.right_R[i] = cP[i];
676 cP = reinterpret_cast<const float *>(&(image_calibration.
left.
P[0][0]));
677 for(uint32_t i=0; i<12; i++) cal.right_P[i] = cP[i];
681 cP =
reinterpret_cast<const float *
>(&(image_calibration.
right.
M[0][0]));
682 for(uint32_t i=0; i<9; i++) cal.right_M[i] = cP[i];
683 cP = reinterpret_cast<const float *>(&(image_calibration.
right.
D[0]));
684 for(uint32_t i=0; i<8; i++) cal.right_D[i] = cP[i];
685 cP = reinterpret_cast<const float *>(&(image_calibration.
right.
R[0][0]));
686 for(uint32_t i=0; i<9; i++) cal.right_R[i] = cP[i];
687 cP = reinterpret_cast<const float *>(&(image_calibration.
right.
P[0][0]));
688 for(uint32_t i=0; i<12; i++) cal.right_P[i] = cP[i];
692 raw_cam_cal_pub_.publish(cal);
698 ROS_WARN(
"Camera: invalid aux camera calibration");
708 std::vector<geometry_msgs::TransformStamped> stamped_transforms{};
710 stamped_transforms.emplace_back();
711 tf2::Transform rectified_left_T_left{toRotation(image_calibration.left.R), tf2::Vector3{0., 0., 0.}};
715 stamped_transforms.back().transform =
tf2::toMsg(rectified_left_T_left);
717 if (has_right_extrinsics)
719 stamped_transforms.emplace_back();
725 stamped_transforms.back().transform =
tf2::toMsg(rectified_right_T_rectified_left.inverse());
727 stamped_transforms.emplace_back();
728 tf2::Transform rectified_right_T_right{toRotation(image_calibration.right.R), tf2::Vector3{0., 0., 0.}};
732 stamped_transforms.back().transform =
tf2::toMsg(rectified_right_T_right);
735 if (has_aux_extrinsics)
739 stamped_transforms.emplace_back();
741 tf2::Vector3{aux_T(0), aux_T(1), aux_T(2)}};
745 stamped_transforms.back().transform =
tf2::toMsg(rectified_aux_T_rectified_left.inverse());
747 stamped_transforms.emplace_back();
748 tf2::Transform rectified_aux_T_aux{toRotation(image_calibration.aux.R), tf2::Vector3{0., 0., 0.}};
752 stamped_transforms.back().transform =
tf2::toMsg(rectified_aux_T_aux);
794 driver_->
addIsolatedCallback(rectCB, Source_Luma_Rectified_Left | Source_Luma_Rectified_Right | Source_Luma_Rectified_Aux,
this);
799 Source_Luma_Left | Source_Luma_Rectified_Left,
this);
822 if (can_support_ground_surface_) {
830 const char *pcColorFrameSyncEnvStringP = getenv(
"MULTISENSE_ROS_PC_COLOR_FRAME_SYNC_OFF");
831 if (NULL != pcColorFrameSyncEnvStringP) {
832 ROS_INFO(
"color point cloud frame sync is disabled");
896 Eigen::Matrix<float, 3, 3> eigen_rot =
897 (Eigen::AngleAxis<float>(extrinsics.
yaw, Eigen::Matrix<float, 3, 1>(0, 0, 1))
898 * Eigen::AngleAxis<float>(extrinsics.
pitch, Eigen::Matrix<float, 3, 1>(0, 1, 0))
899 * Eigen::AngleAxis<float>(extrinsics.
roll, Eigen::Matrix<float, 3, 1>(1, 0, 0))).matrix();
912 std::vector<geometry_msgs::TransformStamped> extrinsic_transforms_(1);
914 tf2::Transform multisense_head_T_origin{tf2_rot, tf2::Vector3{extrinsics.
x, extrinsics.
y, extrinsics.
z}};
918 extrinsic_transforms_[0].transform =
tf2::toMsg(multisense_head_T_origin);
937 multisense_ros::Histogram rh;
941 if (Status_Ok == status) {
942 rh.frame_count = header.
frameId;
945 rh.width = header.
width;
946 rh.height = header.
height;
948 case Source_Chroma_Left:
949 case Source_Chroma_Right:
955 rh.gain = header.
gain;
967 if (Source_Jpeg_Left != header.
source) {
975 throw std::runtime_error(
"Uninitialized stereo calibration manager");
978 const uint32_t height = header.
height;
979 const uint32_t width = header.
width;
980 const uint32_t rgbLength = height * width * 3;
992 tjhandle jpegDecompressor = tjInitDecompress();
993 tjDecompress2(jpegDecompressor,
994 reinterpret_cast<unsigned char*>(const_cast<void*>(header.
imageDataP)),
997 width, 0, height, TJPF_RGB, 0);
998 tjDestroy(jpegDecompressor);
1011 const cv::Mat rgb_image(height, width, CV_8UC3, &(
left_rgb_image_.data[0]));
1016 cv::remap(rgb_image, rect_rgb_image, left_remap->map1, left_remap->map2, cv::INTER_LINEAR);
1032 if (!((Source_Disparity == header.
source &&
1034 (Source_Disparity_Right == header.
source &&
1036 (Source_Disparity_Cost == header.
source &&
1038 (Source_Disparity == header.
source &&
1040 (Source_Disparity_Right == header.
source &&
1050 throw std::runtime_error(
"Uninitialized stereo calibration manager");
1054 case Source_Disparity:
1055 case Source_Disparity_Right:
1057 sensor_msgs::Image *imageP = NULL;
1059 sensor_msgs::CameraInfo camInfo;
1062 stereo_msgs::DisparityImage *stereoDisparityImageP = NULL;
1065 if (Source_Disparity == header.
source) {
1087 imageP->data.resize(imageSize);
1088 memcpy(&imageP->data[0], header.
imageDataP, imageSize);
1090 imageP->header.stamp = t;
1091 imageP->height = header.
height;
1092 imageP->width = header.
width;
1093 imageP->is_bigendian = (htonl(1) == 1);
1098 imageP->step = header.
width;
1102 imageP->step = header.
width * 2;
1113 throw std::runtime_error(
"Stereo calibration manager missing right calibration");
1121 if (camInfo.P[0] != camInfo.P[5])
1123 std::stringstream warning;
1124 warning <<
"Current camera configuration has non-square pixels (fx != fy).";
1125 warning <<
"The stereo_msgs/DisparityImage does not account for";
1126 warning <<
" this. Be careful when reprojecting to a pointcloud.";
1127 ROS_WARN(
"%s", warning.str().c_str());
1134 uint32_t floatingPointImageSize = header.
width * header.
height * 4;
1135 stereoDisparityImageP->image.data.resize(floatingPointImageSize);
1137 stereoDisparityImageP->header.stamp = t;
1139 stereoDisparityImageP->image.height = header.
height;
1140 stereoDisparityImageP->image.width = header.
width;
1141 stereoDisparityImageP->image.is_bigendian = (htonl(1) == 1);
1142 stereoDisparityImageP->image.header.stamp = t;
1143 stereoDisparityImageP->image.header.frame_id = stereoDisparityImageP->header.frame_id;
1145 stereoDisparityImageP->image.step = 4 * header.
width;
1151 stereoDisparityImageP->f = camInfo.P[0];
1158 stereoDisparityImageP->min_disparity = 0;
1160 stereoDisparityImageP->delta_d = 1./16.;
1168 cv::Mat_<uint16_t> tmpImage(header.
height,
1170 reinterpret_cast<uint16_t*>(
1176 cv::Mat_<float> floatingPointImage(header.
height,
1178 reinterpret_cast<float*>(&stereoDisparityImageP->image.data[0]));
1184 floatingPointImage = tmpImage / 16.0;
1186 stereoDisparityPubP->
publish(*stereoDisparityImageP);
1189 camInfoPubP->
publish(camInfo);
1193 case Source_Disparity_Cost:
1217 if (Source_Luma_Left != header.
source &&
1218 Source_Luma_Right != header.
source &&
1219 Source_Luma_Aux != header.
source) {
1221 ROS_ERROR(
"Camera: unexpected mono image source: 0x%x", header.
source);
1229 throw std::runtime_error(
"Uninitialized stereo calibration manager");
1233 case Source_Luma_Left:
1265 case Source_Luma_Right:
1295 case Source_Luma_Aux:
1329 if (Source_Luma_Rectified_Left != header.
source &&
1330 Source_Luma_Rectified_Right != header.
source &&
1331 Source_Luma_Rectified_Aux != header.
source) {
1333 ROS_ERROR(
"Camera: unexpected rectified image source: 0x%x", header.
source);
1341 throw std::runtime_error(
"Uninitialized stereo calibration manager");
1345 case Source_Luma_Rectified_Left:
1383 case Source_Luma_Rectified_Right:
1419 case Source_Luma_Rectified_Aux:
1460 if (Source_Disparity != header.
source) {
1462 ROS_ERROR(
"Camera: unexpected depth image source: 0x%x", header.
source);
1469 if (0 == niDepthSubscribers && 0 == depthSubscribers)
1478 throw std::runtime_error(
"Uninitialized stereo calibration manager");
1481 const float bad_point = std::numeric_limits<float>::quiet_NaN();
1482 const uint32_t depthSize = header.
height * header.
width *
sizeof(float);
1483 const uint32_t niDepthSize = header.
height * header.
width *
sizeof(uint16_t);
1484 const uint32_t imageSize = header.
width * header.
height;
1503 float *depthImageP =
reinterpret_cast<float*
>(&
depth_image_.data[0]);
1504 uint16_t *niDepthImageP =
reinterpret_cast<uint16_t*
>(&
ni_depth_image_.data[0]);
1506 const uint16_t min_ni_depth = std::numeric_limits<uint16_t>::lowest();
1507 const uint16_t max_ni_depth = std::numeric_limits<uint16_t>::max();
1512 throw std::runtime_error(
"Stereo calibration manager missing right calibration");
1531 const float *disparityImageP =
reinterpret_cast<const float*
>(header.
imageDataP);
1533 for (uint32_t i = 0 ; i < imageSize ; ++i)
1535 if (0.0 >= disparityImageP[i])
1537 depthImageP[i] = bad_point;
1538 niDepthImageP[i] = 0;
1542 depthImageP[i] = scale / disparityImageP[i];
1543 niDepthImageP[i] =
static_cast<uint16_t
>(std::min(static_cast<float>(max_ni_depth),
1544 std::max(static_cast<float>(min_ni_depth),
1545 depthImageP[i] * 1000)));
1567 const uint16_t *disparityImageP =
reinterpret_cast<const uint16_t*
>(header.
imageDataP);
1569 for (uint32_t i = 0 ; i < imageSize ; ++i)
1571 if (0 == disparityImageP[i])
1573 depthImageP[i] = bad_point;
1574 niDepthImageP[i] = 0;
1578 depthImageP[i] = scale / disparityImageP[i];
1579 niDepthImageP[i] =
static_cast<uint16_t
>(std::min(static_cast<float>(max_ni_depth),
1580 std::max(static_cast<float>(min_ni_depth),
1581 depthImageP[i] * 1000)));
1590 if (0 != niDepthSubscribers)
1595 if (0 != depthSubscribers)
1605 if (Source_Disparity != header.
source) {
1607 ROS_ERROR(
"Camera: unexpected pointcloud image source: 0x%x", header.
source);
1613 throw std::runtime_error(
"Uninitialized stereo calibration manager");
1619 std::shared_ptr<BufferWrapper<image::Header>> left_luma_rect =
nullptr;
1620 std::shared_ptr<BufferWrapper<image::Header>> left_luma =
nullptr;
1621 std::shared_ptr<BufferWrapper<image::Header>> left_chroma =
nullptr;
1622 std::shared_ptr<BufferWrapper<image::Header>> aux_luma_rectified =
nullptr;
1623 std::shared_ptr<BufferWrapper<image::Header>> aux_chroma_rectified =
nullptr;
1625 const auto left_rect_image =
image_buffers_.find(Source_Luma_Rectified_Left);
1626 if (left_rect_image != std::end(
image_buffers_) && left_rect_image->second->data().frameId == header.
frameId) {
1627 left_luma_rect = left_rect_image->second;
1630 const auto left_luma_image =
image_buffers_.find(Source_Luma_Left);
1631 if (left_luma_image != std::end(
image_buffers_) && left_luma_image->second->data().frameId == header.
frameId) {
1632 left_luma = left_luma_image->second;
1635 const auto chroma_image =
image_buffers_.find(Source_Chroma_Left);
1636 if (chroma_image != std::end(
image_buffers_) && chroma_image->second->data().frameId == header.
frameId) {
1637 left_chroma = chroma_image->second;
1640 const auto aux_luma_rectified_image =
image_buffers_.find(Source_Luma_Rectified_Aux);
1641 if (aux_luma_rectified_image != std::end(
image_buffers_) && aux_luma_rectified_image->second->data().frameId == header.
frameId) {
1642 aux_luma_rectified = aux_luma_rectified_image->second;
1645 const auto aux_chroma_rectified_image =
image_buffers_.find(Source_Chroma_Rectified_Aux);
1646 if (aux_chroma_rectified_image != std::end(
image_buffers_) && aux_chroma_rectified_image->second->data().frameId == header.
frameId) {
1647 aux_chroma_rectified = aux_chroma_rectified_image->second;
1658 if (!(pub_pointcloud || pub_color_pointcloud || pub_organized_pointcloud || pub_color_organized_pointcloud))
1674 if (pub_color_pointcloud)
1680 if (pub_organized_pointcloud)
1689 if (pub_color_organized_pointcloud)
1698 const Eigen::Vector3f invalid_point(std::numeric_limits<float>::quiet_NaN(),
1699 std::numeric_limits<float>::quiet_NaN(),
1700 std::numeric_limits<float>::quiet_NaN());
1705 cv::Mat rectified_color;
1706 if (!
has_aux_camera_ && (pub_color_pointcloud || pub_color_organized_pointcloud))
1708 const auto &luma = left_luma->data();
1719 cv::remap(rgb_image, rect_rgb_image, left_remap->map1, left_remap->map2, cv::INTER_LINEAR);
1721 rectified_color = std::move(rect_rgb_image);
1723 else if(
has_aux_camera_ && (pub_color_pointcloud || pub_color_organized_pointcloud))
1725 const auto &luma = aux_luma_rectified->data();
1738 (header.
width != luma.width || header.
height != luma.height))
1740 cv::Mat resized_rect_rgb_image;
1741 cv::resize(rect_rgb_image,
1742 resized_rect_rgb_image,
1743 cv::Size{
static_cast<int>(header.
width), static_cast<int>(header.
height)},
1744 0, 0, cv::INTER_AREA);
1746 rect_rgb_image = std::move(resized_rect_rgb_image);
1749 rectified_color = std::move(rect_rgb_image);
1755 throw std::runtime_error(
"Stereo calibration manager missing right calibration");
1761 rectified_color.cols, rectified_color.rows);
1766 uint32_t packed_color = 0;
1770 size_t valid_points = 0;
1771 for (
size_t y = 0 ; y < header.
height ; ++y)
1773 for (
size_t x = 0 ; x < header.
width ; ++x)
1775 const size_t index = y * header.
width + x;
1777 float disparity = 0.0f;
1782 disparity =
static_cast<float>(
reinterpret_cast<const uint16_t*
>(header.
imageDataP)[index]) / 16.0f;
1787 disparity =
static_cast<float>(
reinterpret_cast<const float*
>(header.
imageDataP)[index]);
1798 left_camera_info, right_camera_info);
1804 if (!rectified_color.empty())
1811 rectified_color.at<cv::Vec3b>(y, x);
1814 packed_color |= color_pixel[2] << 16 | color_pixel[1] << 8 | color_pixel[0];
1823 if (pub_organized_pointcloud)
1828 if (pub_color_organized_pointcloud)
1836 const bool valid = isValidReprojectedPoint(point, squared_max_range);
1838 if (pub_pointcloud && valid)
1840 writePoint(
luma_point_cloud_, valid_points, point, index, left_luma_rect->data());
1843 if(pub_color_pointcloud && valid)
1848 if (pub_organized_pointcloud)
1853 if (pub_color_organized_pointcloud)
1874 if(pub_color_pointcloud)
1883 if (pub_organized_pointcloud)
1888 if (pub_color_organized_pointcloud)
1901 if(Source_Disparity == header.
source)
1903 const auto image =
image_buffers_.find(Source_Luma_Rectified_Left);
1906 const auto luma_ptr = image->second;
1907 const auto &left_luma_rect = luma_ptr->data();
1909 const uint32_t left_luma_image_size = left_luma_rect.width * left_luma_rect.height;
1911 raw_cam_data_.gray_scale_image.resize(left_luma_image_size);
1913 left_luma_rect.imageDataP,
1914 left_luma_image_size *
sizeof(uint8_t));
1916 raw_cam_data_.frames_per_second = left_luma_rect.framesPerSecond;
1920 raw_cam_data_.time_stamp =
ros::Time(left_luma_rect.timeSeconds, 1000 * left_luma_rect.timeMicroSeconds);
1924 const uint32_t disparity_size = header.
width * header.
height;
1929 disparity_size * header.
bitsPerPixel == 16 ?
sizeof(uint16_t) :
sizeof(uint32_t));
1941 if (Source_Chroma_Left != header.
source &&
1942 Source_Chroma_Rectified_Aux != header.
source &&
1943 Source_Chroma_Aux != header.
source)
1945 ROS_WARN(
"Camera: unexpected color image source: 0x%x", header.
source);
1953 throw std::runtime_error(
"Uninitialized stereo calibration manager");
1958 case Source_Chroma_Left:
1964 if (color_subscribers == 0 && color_rect_subscribers == 0)
1974 const auto luma_ptr = left_luma->second;
1976 if (header.
frameId == luma_ptr->data().frameId) {
1978 const uint32_t height = luma_ptr->data().height;
1979 const uint32_t width = luma_ptr->data().width;
1980 const uint32_t imageSize = 3 * height * width;
2000 if (color_subscribers != 0) {
2006 if (color_rect_subscribers > 0) {
2013 const cv::Mat rgb_image(height, width, CV_8UC3, &(
left_rgb_image_.data[0]));
2016 cv::remap(rgb_image, rect_rgb_image, remaps->map1, remaps->map2, cv::INTER_LINEAR);
2035 case Source_Chroma_Rectified_Aux:
2041 const auto aux_luma =
image_buffers_.find(Source_Luma_Rectified_Aux);
2046 const auto luma_ptr = aux_luma->second;
2048 if (header.
frameId == luma_ptr->data().frameId) {
2050 const uint32_t height = luma_ptr->data().height;
2051 const uint32_t width = luma_ptr->data().width;
2052 const uint32_t imageSize = 3 * height * width;
2079 case Source_Chroma_Aux:
2090 const auto luma_ptr = aux_luma->second;
2092 if (header.
frameId == luma_ptr->data().frameId) {
2093 const uint32_t height = luma_ptr->data().height;
2094 const uint32_t width = luma_ptr->data().width;
2095 const uint32_t imageSize = 3 * height * width;
2127 if (Source_Luma_Rectified_Aux != header.
source &&
2128 Source_Chroma_Rectified_Aux != header.
source &&
2129 Source_Luma_Aux != header.
source &&
2130 Source_Luma_Left != header.
source &&
2131 Source_Chroma_Left != header.
source &&
2132 Source_Luma_Rectified_Left != header.
source) {
2133 ROS_WARN(
"Camera: unexpected colorized image source: 0x%x", header.
source);
2142 if (Source_Ground_Surface_Class_Image != header.
source)
2144 ROS_WARN(
"Camera: unexpected image source: 0x%x", header.
source);
2152 throw std::runtime_error(
"Uninitialized stereo calibration manager");
2157 case Source_Ground_Surface_Class_Image:
2161 if (ground_surface_subscribers == 0)
2164 const uint32_t height = header.
height;
2165 const uint32_t width = header.
width;
2166 const uint32_t imageSize = 3 * height * width;
2187 const size_t row_offset = y * rgb_stride;
2191 const uint8_t *imageP =
reinterpret_cast<const uint8_t*
>(header.
imageDataP);
2219 ROS_WARN(
"Ground surface modelling failed, consider modifying camera extrinsics and/or algorithm parameters");
2225 throw std::runtime_error(
"Uninitialized stereo calibration manager");
2229 Eigen::Map<const Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> controlGrid(
2235 float minMaxAzimuthAngle[2];
2236 minMaxAzimuthAngle[0] = M_PI_2 -
atan(config.cx() / config.fx());
2237 minMaxAzimuthAngle[1] = M_PI_2 +
atan((config.width() - config.cx()) / config.fx());
2259 throw std::runtime_error(
"Uninitialized stereo calibration manager");
2267 multisense_ros::RawCamConfig cfg;
2269 cfg.width = config.
width();
2270 cfg.height = config.
height();
2271 cfg.frames_per_second = config.
fps();
2272 cfg.gain = config.
gain();
2273 cfg.exposure_time = config.
exposure();
2275 cfg.fx = config.
fx();
2276 cfg.fy = config.
fy();
2277 cfg.cx = config.
cx();
2278 cfg.cy = config.
cy();
2279 cfg.tx = config.
tx();
2280 cfg.ty = config.
ty();
2281 cfg.tz = config.
tz();
2282 cfg.roll = config.
roll();
2283 cfg.pitch = config.
pitch();
2284 cfg.yaw = config.
yaw();
2300 throw std::runtime_error(
"Uninitialized stereo calibration manager");
2387 stat.
add(
"pcb: " + pcb.name, pcb.revision);
2418 stat.
summary(diagnostic_msgs::DiagnosticStatus::OK,
"MultiSense Device Info");
2431 stat.
add(
"imu", statusMessage.
imuOk);
2443 stat.
summary(diagnostic_msgs::DiagnosticStatus::OK,
"MultiSense Status: OK");
2445 stat.
summary(diagnostic_msgs::DiagnosticStatus::ERROR,
"MultiSense Status: ERROR - Unable to retrieve status");
2461 if (Status_Ok != status)
2462 ROS_ERROR(
"Camera: failed to stop all streams: %s",
2463 Channel::statusString(status));
2472 for(uint32_t i=0; i<32; i++)
2473 if ((1<<i) & enableMask && 0 ==
stream_map_[(1<<i)]++)
2474 notStarted |= (1<<i);
2476 if (0 != notStarted) {
2479 if (Status_Ok != status)
2480 ROS_ERROR(
"Camera: failed to start streams 0x%x: %s",
2481 notStarted, Channel::statusString(status));
2491 for(uint32_t i=0; i<32; i++)
2492 if ((1<<i) & disableMask && 0 == --
stream_map_[(1<<i)])
2493 notStopped |= (1<<i);
2495 if (0 != notStopped) {
2497 if (Status_Ok != status)
2498 ROS_ERROR(
"Camera: failed to stop streams 0x%x: %s\n",
2499 notStopped, Channel::statusString(status));
virtual Status startStreams(DataSource mask)=0
ros::Publisher left_rgb_cam_info_pub_
const std::string frame_id_rectified_right_
static CRL_CONSTEXPR DataSource Source_Disparity_Cost
image_transport::Publisher right_disparity_pub_
static constexpr char RECT_CAMERA_INFO_TOPIC[]
void maxPointCloudRangeChanged(double range)
ros::Publisher luma_organized_point_cloud_pub_
static CRL_CONSTEXPR DataSource Source_Luma_Aux
void pointCloudCallback(const crl::multisense::image::Header &header)
void rawCamDataCallback(const crl::multisense::image::Header &header)
image_transport::ImageTransport disparity_cost_transport_
image_transport::Publisher left_mono_cam_pub_
std::vector< PcbInfo > pcbs
static const Matrix3x3 & getIdentity()
static constexpr char RAW_CAM_DATA_TOPIC[]
sensor_msgs::Image right_rect_image_
static constexpr char COLOR_CAMERA_INFO_TOPIC[]
void disparityImageCallback(const crl::multisense::image::Header &header)
ros::NodeHandle device_nh_
static CRL_CONSTEXPR DataSource Source_Disparity_Right
tf2_ros::StaticTransformBroadcaster static_tf_broadcaster_
static constexpr char DEPTH_TOPIC[]
ros::Publisher right_stereo_disparity_pub_
static constexpr char MONO_TOPIC[]
ros::Publisher right_rect_cam_info_pub_
void colorImageCallback(const crl::multisense::image::Header &header)
static constexpr char DISPARITY_CAMERA_INFO_TOPIC[]
static CRL_CONSTEXPR DataSource Source_Jpeg_Left
static constexpr char COST_CAMERA_INFO_TOPIC[]
image_transport::ImageTransport left_rect_transport_
sensor_msgs::Image ni_depth_image_
static CRL_CONSTEXPR DataSource Source_Disparity
sensor_msgs::PointCloud2 luma_organized_point_cloud_
sensor_msgs::PointCloud2 luma_point_cloud_
void monoCallback(const crl::multisense::image::Header &header)
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
uint32_t getNumSubscribers() const
void summary(unsigned char lvl, const std::string s)
image_transport::Publisher left_disparity_cost_pub_
sensor_msgs::PointCloud2 color_point_cloud_
ros::Publisher left_stereo_disparity_pub_
ros::Publisher luma_point_cloud_pub_
static CRL_CONSTEXPR DataSource Source_Chroma_Left
static constexpr char GROUND_SURFACE_POINT_SPLINE_TOPIC[]
ros::Publisher depth_cam_info_pub_
virtual Status stopStreams(DataSource mask)=0
ros::Publisher histogram_pub_
ros::Publisher left_mono_cam_info_pub_
uint64_t sensorHardwareMagic
void setHardwareID(const std::string &hwid)
const std::string frame_id_left_
static constexpr char ORGANIZED_POINTCLOUD_TOPIC[]
void diagnosticTimerCallback(const ros::TimerEvent &)
sensor_msgs::Image right_disparity_image_
Publisher advertise(const std::string &base_topic, uint32_t queue_size, bool latch=false)
std::unordered_map< crl::multisense::DataSource, std::shared_ptr< BufferWrapper< crl::multisense::image::Header > > > image_buffers_
virtual Status getImageHistogram(int64_t frameId, image::Histogram &histogram)=0
static constexpr char DEVICE_INFO_TOPIC[]
static constexpr char RECT_TOPIC[]
double border_clip_value_
sensor_msgs::Image depth_image_
image_transport::ImageTransport aux_rgb_transport_
void add(const std::string &name, TaskFunction f)
void disconnectStream(crl::multisense::DataSource disableMask)
image_transport::Publisher aux_mono_cam_pub_
static constexpr char DISPARITY_IMAGE_TOPIC[]
static CRL_CONSTEXPR DataSource Source_Luma_Left
void depthCallback(const crl::multisense::image::Header &header)
ros::Publisher ground_surface_info_pub_
std::string sensorFirmwareBuildDate
void connectStream(crl::multisense::DataSource enableMask)
ros::NodeHandle ground_surface_nh_
ros::Publisher raw_cam_config_pub_
static constexpr char COST_TOPIC[]
sensor_msgs::Image left_disparity_cost_image_
virtual Status getVersionInfo(system::VersionInfo &v)=0
geometry_msgs::TransformStamped t
image_transport::ImageTransport right_mono_transport_
image_transport::ImageTransport left_rgb_transport_
float powerSupplyTemperature
void colorizeCallback(const crl::multisense::image::Header &header)
sensor_msgs::Image ground_surface_image_
ros::Publisher right_mono_cam_info_pub_
const std::string frame_id_right_
stereo_msgs::DisparityImage left_stereo_disparity_
bool can_support_ground_surface_
image_transport::ImageTransport aux_mono_transport_
ros::Publisher aux_rgb_cam_info_pub_
std::vector< uint32_t > data
static CRL_CONSTEXPR DataSource Source_Luma_Rectified_Aux
ros::Timer diagnostic_trigger_
image_transport::Publisher right_mono_cam_pub_
void borderClipChanged(const BorderClip &borderClipType, double borderClipValue)
StreamMapType stream_map_
crl::multisense::system::DeviceInfo device_info_
CameraPublisher advertiseCamera(const std::string &base_topic, uint32_t queue_size, bool latch=false)
image_transport::CameraPublisher aux_rgb_rect_cam_pub_
image_transport::Publisher ground_surface_cam_pub_
void publish(const boost::shared_ptr< M > &message) const
static CRL_CONSTEXPR DataSource Source_Luma_Right
ros::Publisher aux_rect_cam_info_pub_
sensor_msgs::Image left_mono_image_
image_transport::Publisher ni_depth_cam_pub_
void rectCallback(const crl::multisense::image::Header &header)
virtual Status removeIsolatedCallback(image::Callback callback)=0
virtual Status addIsolatedCallback(image::Callback callback, DataSource imageSourceMask, void *userDataP=NULL)=0
image_transport::ImageTransport aux_rgb_rect_transport_
const std::string frame_id_rectified_left_
void updateConfig(const crl::multisense::image::Config &config)
image_transport::Publisher left_disparity_pub_
ros::Publisher raw_cam_data_pub_
image_transport::CameraPublisher left_rgb_rect_cam_pub_
INLINE Rall1d< T, V, S > atan(const Rall1d< T, V, S > &x)
void groundSurfaceCallback(const crl::multisense::image::Header &header)
float leftImagerTemperature
ros::Publisher left_disp_cam_info_pub_
image_transport::Publisher depth_cam_pub_
uint32_t getNumSubscribers() const
BorderClip border_clip_type_
image_transport::ImageTransport ground_surface_transport_
constexpr Eigen::Matrix< T, 3, 1 > ycbcrToBgr(const crl::multisense::image::Header &luma, const crl::multisense::image::Header &chroma, size_t u, size_t v)
void groundSurfaceSplineDrawParametersChanged(const ground_surface_utilities::SplineDrawParameters &spline_draw_params)
static constexpr char GROUND_SURFACE_INFO_TOPIC[]
image_transport::ImageTransport aux_rect_transport_
void deviceStatusDiagnostic(diagnostic_updater::DiagnosticStatusWrapper &stat)
virtual Status getImageCalibration(image::Calibration &c)=0
Struct containing parameters for drawing a pointcloud representation of a B-Spline model...
const std::string TYPE_32FC1
ros::NodeHandle right_nh_
image_transport::CameraPublisher right_rect_cam_pub_
image_transport::ImageTransport left_mono_transport_
static constexpr char GROUND_SURFACE_IMAGE_TOPIC[]
uint32_t hardwareRevision
image_transport::CameraPublisher aux_rect_cam_pub_
ros::Publisher raw_cam_cal_pub_
static CRL_CONSTEXPR Status Status_Ok
image_transport::CameraPublisher left_rect_cam_pub_
bool processingPipelineOk
static CRL_CONSTEXPR DataSource Source_Chroma_Aux
sensor_msgs::Image left_rect_image_
diagnostic_updater::Updater diagnostic_updater_
ros::Publisher right_disp_cam_info_pub_
crl::multisense::Channel * driver_
void deviceInfoDiagnostic(diagnostic_updater::DiagnosticStatusWrapper &stat)
void groundSurfaceSplineCallback(const crl::multisense::ground_surface::Header &header)
ros::Publisher device_info_pub_
static constexpr char RAW_CAM_CAL_TOPIC[]
image_transport::Publisher left_rgb_cam_pub_
const std::string frame_id_rectified_aux_
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void extrinsicsChanged(crl::multisense::system::ExternalCalibration extrinsics)
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
static constexpr char RECT_COLOR_CAMERA_INFO_TOPIC[]
static constexpr char COLOR_POINTCLOUD_TOPIC[]
static constexpr char OPENNI_DEPTH_TOPIC[]
static constexpr char COLOR_TOPIC[]
image_transport::ImageTransport left_rgb_rect_transport_
std::shared_ptr< StereoCalibrationManager > stereo_calibration_manager_
ros::NodeHandle calibration_nh_
ros::Publisher aux_rgb_rect_cam_info_pub_
void publish(const sensor_msgs::Image &message) const
sensor_msgs::Image aux_rgb_image_
sensor_msgs::Image left_rgb_image_
sensor_msgs::Image right_mono_image_
image_transport::ImageTransport depth_transport_
ros::Publisher left_rgb_rect_cam_info_pub_
void histogramCallback(const crl::multisense::image::Header &header)
ground_surface_utilities::SplineDrawParameters spline_draw_params_
stereo_msgs::DisparityImage right_stereo_disparity_
VersionType sensorFirmwareVersion
static constexpr char RECT_COLOR_TOPIC[]
double pointcloud_max_range_
image_transport::ImageTransport right_rect_transport_
ros::Publisher ground_surface_spline_pub_
static CRL_CONSTEXPR DataSource Source_Chroma_Rectified_Aux
ros::Publisher left_cost_cam_info_pub_
virtual Status getDeviceStatus(system::StatusMessage &status)=0
static constexpr char DEPTH_CAMERA_INFO_TOPIC[]
static constexpr char HISTOGRAM_TOPIC[]
image_transport::Publisher aux_rgb_cam_pub_
float nominalRelativeAperture
void publish(const sensor_msgs::Image &image, const sensor_msgs::CameraInfo &info) const
uint32_t exposure() const
image_transport::ImageTransport ni_depth_transport_
image_transport::ImageTransport disparity_right_transport_
static constexpr char POINTCLOUD_TOPIC[]
sensor_msgs::Image aux_mono_image_
ros::Publisher left_rect_cam_info_pub_
std::vector< uint8_t > pointcloud_rect_color_buffer_
virtual Status getDeviceInfo(system::DeviceInfo &info)=0
sensor_msgs::PointCloud2 eigenToPointcloud(const std::vector< Eigen::Vector3f, Eigen::aligned_allocator< Eigen::Vector3f >> &input, const std::string &frame_id)
Convert an eigen representation of a pointcloud to a ROS sensor_msgs::PointCloud2 format...
Eigen::Matrix< uint8_t, 3, 1 > groundSurfaceClassToPixelColor(const uint8_t value)
Look up table to convert a ground surface class value into into a color for visualization (out-of-bou...
void jpegImageCallback(const crl::multisense::image::Header &header)
sensor_msgs::Image left_disparity_image_
ros::Publisher color_organized_point_cloud_pub_
float rightImagerTemperature
sensor_msgs::Image aux_rgb_rect_image_
static constexpr char MONO_CAMERA_INFO_TOPIC[]
static CRL_CONSTEXPR DataSource Source_Luma_Rectified_Right
image_transport::ImageTransport disparity_left_transport_
void add(const std::string &key, const T &val)
const std::string frame_id_origin_
sensor_msgs::PointCloud2 color_organized_point_cloud_
crl::multisense::system::VersionInfo version_info_
static constexpr char COLOR_ORGANIZED_POINTCLOUD_TOPIC[]
uint32_t getNumSubscribers() const
sensor_msgs::Image left_rgb_rect_image_
const std::string frame_id_aux_
void publishAllCameraInfo()
ros::Publisher aux_mono_cam_info_pub_
multisense_ros::RawCamData raw_cam_data_
uint64_t sensorHardwareVersion
ros::Publisher color_point_cloud_pub_
virtual Status getImageConfig(image::Config &c)=0
sensor_msgs::Image aux_rect_image_
std::vector< uint8_t > pointcloud_color_buffer_
std::vector< Eigen::Vector3f, Eigen::aligned_allocator< Eigen::Vector3f > > convertSplineToPointcloud(const Eigen::Matrix< float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > &controlGrid, const SplineDrawParameters &splineDrawParams, const double pointcloudMaxRange, const float *xzCellOrigin, const float *xzCellSize, const float *minMaxAzimuthAngle, const float *extrinsics, const float *quadraticParams, const float baseline)
Generate a pointcloud representation of a b-spline ground surface model for visualization.
static constexpr char DISPARITY_TOPIC[]
static constexpr char RAW_CAM_CONFIG_TOPIC[]
static CRL_CONSTEXPR DataSource Source_Luma_Rectified_Left