RealSense: fixed color rectification. Fixed ZR300 odometry frame.

This commit is contained in:
matlabbe
2018-09-26 20:51:12 -04:00
parent 0c2287df77
commit 5e08da51aa
7 changed files with 625 additions and 152 deletions

View File

@@ -379,6 +379,7 @@ class RTABMAP_EXP CameraRealSense :
{ {
public: public:
static bool available(); static bool available();
enum RGBSource {kColor, kInfrared, kFishEye};
public: public:
// default local transform z in, x right, y down)); // default local transform z in, x right, y down));
@@ -391,11 +392,8 @@ public:
const Transform & localTransform = Transform::getIdentity()); const Transform & localTransform = Transform::getIdentity());
virtual ~CameraRealSense(); virtual ~CameraRealSense();
void setDepthScaledToRGBSize(bool enabled) { void setDepthScaledToRGBSize(bool enabled);
#ifdef RTABMAP_REALSENSE void setRGBSource(RGBSource source);
depthScaledToRGBSize_ = enabled;
#endif
}
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = ""); virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
virtual bool isCalibrated() const; virtual bool isCalibrated() const;
virtual std::string getSerial() const; virtual std::string getSerial() const;
@@ -413,6 +411,9 @@ private:
int presetDepth_; int presetDepth_;
bool computeOdometry_; bool computeOdometry_;
bool depthScaledToRGBSize_; bool depthScaledToRGBSize_;
RGBSource rgbSource_;
CameraModel cameraModel_;
std::vector<int> rsRectificationTable_;
int motionSeq_[2]; int motionSeq_[2];
rs::slam::slam * slam_; rs::slam::slam * slam_;

View File

@@ -278,26 +278,34 @@ bool CameraModel::load(const std::string & directory, const std::string & camera
n["data"] >> data; n["data"] >> data;
UASSERT(rows*cols == (int)data.size()); UASSERT(rows*cols == (int)data.size());
UASSERT(rows == 1 && (cols == 4 || cols == 5 || cols == 8)); UASSERT(rows == 1 && (cols == 4 || cols == 5 || cols == 8));
std::string distortionModel = (std::string)n["distortion_model"]; D_ = cv::Mat(rows, cols, CV_64FC1, data.data()).clone();
if(uStrContains(distortionModel, "fisheye") ||
uStrContains(distortionModel, "equidistant"))
{
D_ = cv::Mat::zeros(1,6,CV_64FC1);
D_.at<double>(0,0) = data[0];
D_.at<double>(0,1) = data[1];
D_.at<double>(0,4) = data[2];
D_.at<double>(0,5) = data[3];
}
else
{
D_ = cv::Mat(rows, cols, CV_64FC1, data.data()).clone();
}
} }
else else
{ {
UWARN("Missing \"distorsion_coefficients\" field in \"%s\"", filePath.c_str()); UWARN("Missing \"distorsion_coefficients\" field in \"%s\"", filePath.c_str());
} }
n = fs["distortion_model"];
if(n.type() != cv::FileNode::NONE)
{
std::string distortionModel = (std::string)n;
if(D_.cols>=4 &&
(uStrContains(distortionModel, "fisheye") ||
uStrContains(distortionModel, "equidistant")))
{
cv::Mat D = cv::Mat::zeros(1,6,CV_64FC1);
D.at<double>(0,0) = D_.at<double>(0,0);
D.at<double>(0,1) = D_.at<double>(0,1);
D.at<double>(0,4) = D_.at<double>(0,2);
D.at<double>(0,5) = D_.at<double>(0,3);
D_ = D;
}
}
else
{
UWARN("Missing \"distortion_model\" field in \"%s\"", filePath.c_str());
}
n = fs["rectification_matrix"]; n = fs["rectification_matrix"];
if(n.type() != cv::FileNode::NONE) if(n.type() != cv::FileNode::NONE)
{ {
@@ -400,7 +408,7 @@ bool CameraModel::save(const std::string & directory) const
// compaibility with ROS // compaibility with ROS
if(D_.cols == 6) if(D_.cols == 6)
{ {
fs << "distortion_model" << "fisheye"; // equidistant fs << "distortion_model" << "equidistant"; // equidistant, fisheye
} }
else if(D.cols > 5) else if(D.cols > 5)
{ {

View File

@@ -2618,6 +2618,7 @@ CameraRealSense::CameraRealSense(
presetDepth_(presetDepth), presetDepth_(presetDepth),
computeOdometry_(computeOdometry), computeOdometry_(computeOdometry),
depthScaledToRGBSize_(false), depthScaledToRGBSize_(false),
rgbSource_(kColor),
slam_(0) slam_(0)
#endif #endif
{ {
@@ -2631,14 +2632,18 @@ CameraRealSense::~CameraRealSense()
UDEBUG(""); UDEBUG("");
if(dev_) if(dev_)
{ {
if(slam_!=0) try
{ {
dev_->stop(rs::source::all_sources); if(slam_!=0)
} {
else dev_->stop(rs::source::all_sources);
{ }
dev_->stop(); else
{
dev_->stop();
}
} }
catch(const rs::error & error){UWARN("%s", error.what());}
dev_ = 0; dev_ = 0;
} }
UDEBUG(""); UDEBUG("");
@@ -2685,6 +2690,118 @@ bool setStreamConfigIntrin(
} }
#endif #endif
void CameraRealSense::setDepthScaledToRGBSize(bool enabled) {
#ifdef RTABMAP_REALSENSE
depthScaledToRGBSize_ = enabled;
#endif
}
void CameraRealSense::setRGBSource(RGBSource source)
{
#ifdef RTABMAP_REALSENSE
rgbSource_ = source;
#endif
}
#ifdef RTABMAP_REALSENSE
template<class GET_DEPTH, class TRANSFER_PIXEL> void align_images(const rs_intrinsics & depth_intrin, const rs_extrinsics & depth_to_other, const rs_intrinsics & other_intrin, GET_DEPTH get_depth, TRANSFER_PIXEL transfer_pixel)
{
// Iterate over the pixels of the depth image
#pragma omp parallel for schedule(dynamic)
for(int depth_y = 0; depth_y < depth_intrin.height; ++depth_y)
{
int depth_pixel_index = depth_y * depth_intrin.width;
for(int depth_x = 0; depth_x < depth_intrin.width; ++depth_x, ++depth_pixel_index)
{
// Skip over depth pixels with the value of zero, we have no depth data so we will not write anything into our aligned images
if(float depth = get_depth(depth_pixel_index))
{
// Map the top-left corner of the depth pixel onto the other image
float depth_pixel[2] = {depth_x-0.5f, depth_y-0.5f}, depth_point[3], other_point[3], other_pixel[2];
rs_deproject_pixel_to_point(depth_point, &depth_intrin, depth_pixel, depth);
rs_transform_point_to_point(other_point, &depth_to_other, depth_point);
rs_project_point_to_pixel(other_pixel, &other_intrin, other_point);
const int other_x0 = static_cast<int>(other_pixel[0] + 0.5f);
const int other_y0 = static_cast<int>(other_pixel[1] + 0.5f);
// Map the bottom-right corner of the depth pixel onto the other image
depth_pixel[0] = depth_x+0.5f; depth_pixel[1] = depth_y+0.5f;
rs_deproject_pixel_to_point(depth_point, &depth_intrin, depth_pixel, depth);
rs_transform_point_to_point(other_point, &depth_to_other, depth_point);
rs_project_point_to_pixel(other_pixel, &other_intrin, other_point);
const int other_x1 = static_cast<int>(other_pixel[0] + 0.5f);
const int other_y1 = static_cast<int>(other_pixel[1] + 0.5f);
if(other_x0 < 0 || other_y0 < 0 || other_x1 >= other_intrin.width || other_y1 >= other_intrin.height) continue;
// Transfer between the depth pixels and the pixels inside the rectangle on the other image
for(int y=other_y0; y<=other_y1; ++y) for(int x=other_x0; x<=other_x1; ++x) transfer_pixel(depth_pixel_index, y * other_intrin.width + x);
}
}
}
}
typedef uint8_t byte;
void align_z_to_other(byte * z_aligned_to_other, const uint16_t * z_pixels, float z_scale, const rs_intrinsics & z_intrin, const rs_extrinsics & z_to_other, const rs_intrinsics & other_intrin)
{
auto out_z = (uint16_t *)(z_aligned_to_other);
align_images(z_intrin, z_to_other, other_intrin,
[z_pixels, z_scale](int z_pixel_index) { return z_scale * z_pixels[z_pixel_index]; },
[out_z, z_pixels](int z_pixel_index, int other_pixel_index) { out_z[other_pixel_index] = out_z[other_pixel_index] ? std::min(out_z[other_pixel_index],z_pixels[z_pixel_index]) : z_pixels[z_pixel_index]; });
}
void align_disparity_to_other(byte * disparity_aligned_to_other, const uint16_t * disparity_pixels, float disparity_scale, const rs_intrinsics & disparity_intrin, const rs_extrinsics & disparity_to_other, const rs_intrinsics & other_intrin)
{
auto out_disparity = (uint16_t *)(disparity_aligned_to_other);
align_images(disparity_intrin, disparity_to_other, other_intrin,
[disparity_pixels, disparity_scale](int disparity_pixel_index) { return disparity_scale / disparity_pixels[disparity_pixel_index]; },
[out_disparity, disparity_pixels](int disparity_pixel_index, int other_pixel_index) { out_disparity[other_pixel_index] = disparity_pixels[disparity_pixel_index]; });
}
template<int N> struct bytes { char b[N]; };
template<int N, class GET_DEPTH> void align_other_to_depth_bytes(byte * other_aligned_to_depth, GET_DEPTH get_depth, const rs_intrinsics & depth_intrin, const rs_extrinsics & depth_to_other, const rs_intrinsics & other_intrin, const byte * other_pixels)
{
auto in_other = (const bytes<N> *)(other_pixels);
auto out_other = (bytes<N> *)(other_aligned_to_depth);
align_images(depth_intrin, depth_to_other, other_intrin, get_depth,
[out_other, in_other](int depth_pixel_index, int other_pixel_index) { out_other[depth_pixel_index] = in_other[other_pixel_index]; });
}
/////////////////////////
// Image rectification //
/////////////////////////
std::vector<int> compute_rectification_table(const rs_intrinsics & rect_intrin, const rs_extrinsics & rect_to_unrect, const rs_intrinsics & unrect_intrin)
{
std::vector<int> rectification_table;
rectification_table.resize(rect_intrin.width * rect_intrin.height);
align_images(rect_intrin, rect_to_unrect, unrect_intrin, [](int) { return 1.0f; },
[&rectification_table](int rect_pixel_index, int unrect_pixel_index) { rectification_table[rect_pixel_index] = unrect_pixel_index; });
return rectification_table;
}
template<class T> void rectify_image_pixels(T * rect_pixels, const std::vector<int> & rectification_table, const T * unrect_pixels)
{
for(auto entry : rectification_table) *rect_pixels++ = unrect_pixels[entry];
}
void rectify_image(uint8_t * rect_pixels, const std::vector<int> & rectification_table, const uint8_t * unrect_pixels, rs_format format)
{
switch(format)
{
case RS_FORMAT_Y8:
return rectify_image_pixels((bytes<1> *)rect_pixels, rectification_table, (const bytes<1> *)unrect_pixels);
case RS_FORMAT_Y16: case RS_FORMAT_Z16:
return rectify_image_pixels((bytes<2> *)rect_pixels, rectification_table, (const bytes<2> *)unrect_pixels);
case RS_FORMAT_RGB8: case RS_FORMAT_BGR8:
return rectify_image_pixels((bytes<3> *)rect_pixels, rectification_table, (const bytes<3> *)unrect_pixels);
case RS_FORMAT_RGBA8: case RS_FORMAT_BGRA8:
return rectify_image_pixels((bytes<4> *)rect_pixels, rectification_table, (const bytes<4> *)unrect_pixels);
default:
assert(false); // NOTE: rectify_image_pixels(...) is not appropriate for RS_FORMAT_YUYV images, no logic prevents U/V channels from being written to one another
}
}
#endif
bool CameraRealSense::init(const std::string & calibrationFolder, const std::string & cameraName) bool CameraRealSense::init(const std::string & calibrationFolder, const std::string & cameraName)
{ {
UDEBUG(""); UDEBUG("");
@@ -2692,10 +2809,22 @@ bool CameraRealSense::init(const std::string & calibrationFolder, const std::str
if(dev_) if(dev_)
{ {
dev_->stop(rs::source::all_sources); try
{
if(slam_!=0)
{
dev_->stop(rs::source::all_sources);
}
else
{
dev_->stop();
}
}
catch(const rs::error & error){UWARN("%s", error.what());}
dev_ = 0; dev_ = 0;
} }
bufferedFrames_.clear(); bufferedFrames_.clear();
rsRectificationTable_.clear();
#ifdef RTABMAP_REALSENSE_SLAM #ifdef RTABMAP_REALSENSE_SLAM
motionSeq_[0] = motionSeq_[1] = 0; motionSeq_[0] = motionSeq_[1] = 0;
@@ -2735,29 +2864,78 @@ bool CameraRealSense::init(const std::string & calibrationFolder, const std::str
UINFO(" Preset RGB: %d", presetRGB_); UINFO(" Preset RGB: %d", presetRGB_);
UINFO(" Preset Depth: %d", presetDepth_); UINFO(" Preset Depth: %d", presetDepth_);
bool computeOdometry = false; #ifndef RTABMAP_REALSENSE_SLAM
#ifdef RTABMAP_REALSENSE_SLAM computeOdometry_ = false;
if (name.find("ZR300") != std::string::npos && computeOdometry_)
{
// Only enable ZR300 functionality if fisheye stream is enabled.
// Accel/Gyro automatically enabled when fisheye requested
computeOdometry = true;
}
#endif #endif
if (name.find("ZR300") == std::string::npos)
{
// Only enable ZR300 functionality odometry if fisheye stream is enabled.
// Accel/Gyro automatically enabled when fisheye requested
computeOdometry_ = false;
// Only ZR300 has fisheye
if(rgbSource_ == kFishEye)
{
UWARN("Fisheye cannot be used with %s camera, using color instead...", name.c_str());
rgbSource_ = kColor;
}
}
rs::intrinsics depth_intrin;
rs::intrinsics fisheye_intrin;
rs::intrinsics color_intrin;
// Configure depth and color to run with the device's preferred settings // Configure depth and color to run with the device's preferred settings
UINFO("Enabling streams..."); UINFO("Enabling streams...");
// R200: // R200:
// 0=640x480 vs 480x360 // 0=640x480 vs 480x360
// 1=1920x1080 vs 640x480 // 1=1920x1080 vs 640x480
// 2=640x480 vs 320x240 // 2=640x480 vs 320x240
dev_->enable_stream(rs::stream::depth, (rs::preset)presetDepth_); try {
dev_->enable_stream(rs::stream::color, (rs::preset)presetRGB_);
rs::intrinsics depth_intrin = dev_->get_stream_intrinsics(rs::stream::depth); // left/rgb stream
rs::intrinsics color_intrin = dev_->get_stream_intrinsics(rs::stream::color); if(rgbSource_==kFishEye || computeOdometry_)
UINFO(" RGB: %dx%d", color_intrin.width, color_intrin.height); {
UINFO(" Depth: %dx%d", depth_intrin.width, depth_intrin.height); dev_->enable_stream(rs::stream::fisheye, 640, 480, rs::format::raw8, 30);
if(computeOdometry_)
{
// Needed to align image timestamps to common clock-domain with the motion events
dev_->set_option(rs::option::fisheye_strobe, 1);
}
// This option causes the fisheye image to be acquired in-sync with the depth image.
dev_->set_option(rs::option::fisheye_external_trigger, 1);
dev_->set_option(rs::option::fisheye_color_auto_exposure, 1);
fisheye_intrin = dev_->get_stream_intrinsics(rs::stream::fisheye);
UINFO(" Fisheye: %dx%d", fisheye_intrin.width, fisheye_intrin.height);
if(rgbSource_==kFishEye)
{
color_intrin = fisheye_intrin; // not rectified
}
}
if(rgbSource_!=kFishEye)
{
dev_->enable_stream(rs::stream::color, (rs::preset)presetRGB_);
color_intrin = dev_->get_stream_intrinsics(rs::stream::rectified_color); // rectified
UINFO(" RGB: %dx%d", color_intrin.width, color_intrin.height);
if(rgbSource_==kInfrared)
{
dev_->enable_stream(rs::stream::infrared, (rs::preset)presetRGB_);
color_intrin = dev_->get_stream_intrinsics(rs::stream::infrared); // rectified
UINFO(" IR left: %dx%d", color_intrin.width, color_intrin.height);
}
}
dev_->enable_stream(rs::stream::depth, (rs::preset)presetDepth_);
depth_intrin = dev_->get_stream_intrinsics(rs::stream::depth); // rectified
UINFO(" Depth: %dx%d", depth_intrin.width, depth_intrin.height);
}
catch(const rs::error & error)
{
UERROR("Failed starting the streams: %s", error.what());
return false;
}
Transform imu2Camera = Transform::getIdentity();
#ifdef RTABMAP_REALSENSE_SLAM #ifdef RTABMAP_REALSENSE_SLAM
UDEBUG("Setup frame callback"); UDEBUG("Setup frame callback");
@@ -2787,9 +2965,50 @@ bool CameraRealSense::init(const std::string & calibrationFolder, const std::str
frame.get_stride() frame.get_stride()
}; };
cv::Mat image; cv::Mat image;
if(frame.get_format() == rs::format::raw8) if(frame.get_format() == rs::format::raw8 || frame.get_format() == rs::format::y8)
{ {
image = cv::Mat(height, width, CV_8UC1, (unsigned char*)frame.get_data()); image = cv::Mat(height, width, CV_8UC1, (unsigned char*)frame.get_data());
if(frame.get_stream_type() == rs::stream::fisheye)
{
// fisheye always received just after the depth image (doesn't have exact timestamp with depth)
if(bufferedFrames_.size())
{
bufferedFrames_.rbegin()->second.first = image.clone();
UScopeMutex lock(dataMutex_);
bool notify = lastSyncFrames_.first.empty();
lastSyncFrames_ = bufferedFrames_.rbegin()->second;
if(notify)
{
dataReady_.release();
}
bufferedFrames_.clear();
}
}
else if(frame.get_stream_type() == rs::stream::infrared) // infrared (does have exact timestamp with depth)
{
if(bufferedFrames_.find(frame.get_timestamp()) != bufferedFrames_.end())
{
bufferedFrames_.find(frame.get_timestamp())->second.first = image.clone();
UScopeMutex lock(dataMutex_);
bool notify = lastSyncFrames_.first.empty();
lastSyncFrames_ = bufferedFrames_.find(frame.get_timestamp())->second;
if(notify)
{
dataReady_.release();
}
bufferedFrames_.erase(frame.get_timestamp());
}
else
{
bufferedFrames_.insert(std::make_pair(frame.get_timestamp(), std::make_pair(image.clone(), cv::Mat())));
}
if(bufferedFrames_.size()>5)
{
UWARN("Frames cannot be synchronized!");
bufferedFrames_.clear();
}
return;
}
} }
else if(frame.get_format() == rs::format::z16) else if(frame.get_format() == rs::format::z16)
{ {
@@ -2818,7 +3037,15 @@ bool CameraRealSense::init(const std::string & calibrationFolder, const std::str
} }
else if(frame.get_format() == rs::format::rgb8) else if(frame.get_format() == rs::format::rgb8)
{ {
image = cv::Mat(height, width, CV_8UC3, (unsigned char*)frame.get_data()); if(rsRectificationTable_.size())
{
image = cv::Mat(height, width, CV_8UC3);
rectify_image(image.data, rsRectificationTable_, (unsigned char*)frame.get_data(), (rs_format)frame.get_format());
}
else
{
image = cv::Mat(height, width, CV_8UC3, (unsigned char*)frame.get_data());
}
if(bufferedFrames_.find(frame.get_timestamp()) != bufferedFrames_.end()) if(bufferedFrames_.find(frame.get_timestamp()) != bufferedFrames_.end())
{ {
bufferedFrames_.find(frame.get_timestamp())->second.first = image.clone(); bufferedFrames_.find(frame.get_timestamp())->second.first = image.clone();
@@ -2868,26 +3095,27 @@ bool CameraRealSense::init(const std::string & calibrationFolder, const std::str
} }
}; };
UDEBUG("");
// Setup stream callback for stream // Setup stream callback for stream
if(computeOdometry) if(computeOdometry_ || rgbSource_ == kFishEye)
{ {
dev_->set_frame_callback(rs::stream::fisheye, frameCallback); dev_->set_frame_callback(rs::stream::fisheye, frameCallback);
} }
dev_->set_frame_callback(rs::stream::depth, frameCallback); if(rgbSource_ == kInfrared)
dev_->set_frame_callback(rs::stream::color, frameCallback);
if (computeOdometry)
{ {
dev_->enable_stream(rs::stream::fisheye, 640, 480, rs::format::raw8, 30); dev_->set_frame_callback(rs::stream::infrared, frameCallback);
rs::intrinsics fisheye_intrin = dev_->get_stream_intrinsics(rs::stream::fisheye); }
UINFO(" Fish: %dx%d", fisheye_intrin.width, fisheye_intrin.height); else if(rgbSource_ == kColor)
{
dev_->set_frame_callback(rs::stream::color, frameCallback);
}
// Needed to align image timestamps to common clock-domain with the motion events dev_->set_frame_callback(rs::stream::depth, frameCallback);
dev_->set_option(rs::option::fisheye_strobe, 1);
// This option causes the fisheye image to be aquired in-sync with the depth image.
dev_->set_option(rs::option::fisheye_external_trigger, 1);
dev_->set_option(rs::option::fisheye_color_auto_exposure, 1);
UDEBUG("");
if (computeOdometry_)
{
UDEBUG("Setup motion callback"); UDEBUG("Setup motion callback");
//define callback to the motion events and set it. //define callback to the motion events and set it.
std::function<void(rs::motion_data)> motion_callback; std::function<void(rs::motion_data)> motion_callback;
@@ -2995,23 +3223,137 @@ bool CameraRealSense::init(const std::string & calibrationFolder, const std::str
return false; return false;
} }
dev_->start(rs::source::all_sources); rs::extrinsics fisheye2imu = dev_->get_motion_extrinsics_from(rs::stream::fisheye);
imu2Camera = Transform(
fisheye2imu.rotation[0], fisheye2imu.rotation[1], fisheye2imu.rotation[2], fisheye2imu.translation[0],
fisheye2imu.rotation[3], fisheye2imu.rotation[4], fisheye2imu.rotation[5], fisheye2imu.translation[1],
fisheye2imu.rotation[6], fisheye2imu.rotation[7], fisheye2imu.rotation[8], fisheye2imu.translation[2]).inverse();
if(rgbSource_ == kInfrared)
{
rs::extrinsics color2Fisheye = dev_->get_extrinsics(rs::stream::fisheye, rs::stream::infrared);
Transform fisheye2Color = Transform(
color2Fisheye.rotation[0], color2Fisheye.rotation[1], color2Fisheye.rotation[2], color2Fisheye.translation[0],
color2Fisheye.rotation[3], color2Fisheye.rotation[4], color2Fisheye.rotation[5], color2Fisheye.translation[1],
color2Fisheye.rotation[6], color2Fisheye.rotation[7], color2Fisheye.rotation[8], color2Fisheye.translation[2]).inverse();
imu2Camera *= fisheye2Color;
}
else if(rgbSource_ == kColor)
{
rs::extrinsics color2Fisheye = dev_->get_extrinsics(rs::stream::fisheye, rs::stream::rectified_color);
Transform fisheye2Color = Transform(
color2Fisheye.rotation[0], color2Fisheye.rotation[1], color2Fisheye.rotation[2], color2Fisheye.translation[0],
color2Fisheye.rotation[3], color2Fisheye.rotation[4], color2Fisheye.rotation[5], color2Fisheye.translation[1],
color2Fisheye.rotation[6], color2Fisheye.rotation[7], color2Fisheye.rotation[8], color2Fisheye.translation[2]).inverse();
imu2Camera *= fisheye2Color;
}
UDEBUG("start device!");
try
{
dev_->start(rs::source::all_sources);
}
catch(const rs::error & error)
{
UERROR("Failed starting the device: %s (try to unplug/plug the camera)", error.what());
return false;
}
} }
else else
{ {
dev_->start(); UDEBUG("start device!");
try
{
dev_->start();
}
catch(const rs::error & error)
{
UERROR("Failed starting the device: %s (try to unplug/plug the camera)", error.what());
return false;
}
} }
#else #else
dev_->start();
try { try {
dev_->start();
dev_->wait_for_frames(); dev_->wait_for_frames();
} }
catch (const rs::error & e) catch (const rs::error & e)
{ {
UERROR("Exception: %s", e.what()); UERROR("Exception: %s (try to unplug/plug the camera)", e.what());
} }
#endif #endif
cv::Mat D;
if(rgbSource_ == kFishEye)
{
// ftheta/equidistant model
D = cv::Mat::zeros(1,6,CV_64FC1);
D.at<double>(0,0) = color_intrin.coeffs[0];
D.at<double>(0,1) = color_intrin.coeffs[1];
D.at<double>(0,4) = color_intrin.coeffs[2];
D.at<double>(0,5) = color_intrin.coeffs[3];
}
else
{
// Brown-Conrady / radtan
D = cv::Mat::zeros(1,5,CV_64FC1);
D.at<double>(0,0) = color_intrin.coeffs[0];
D.at<double>(0,1) = color_intrin.coeffs[1];
D.at<double>(0,2) = color_intrin.coeffs[2];
D.at<double>(0,3) = color_intrin.coeffs[3];
D.at<double>(0,4) = color_intrin.coeffs[4];
}
cv::Mat K = cv::Mat::eye(3, 3, CV_64FC1);
K.at<double>(0,0) = color_intrin.fx;
K.at<double>(1,1) = color_intrin.fy;
K.at<double>(0,2) = color_intrin.ppx;
K.at<double>(1,2) = color_intrin.ppy;
cv::Mat R = cv::Mat::eye(3, 3, CV_64FC1);
cv::Mat P = cv::Mat::eye(3, 4, CV_64FC1);
K(cv::Range(0,2), cv::Range(0,3)).copyTo(P(cv::Range(0,2), cv::Range(0,3)));
cameraModel_ = CameraModel(
dev_->get_name(),
cv::Size(color_intrin.width, color_intrin.height),
K,
D,
R,
P,
this->getLocalTransform()*imu2Camera);
UDEBUG("");
if(rgbSource_ == kColor)
{
rs::extrinsics rect_to_unrect = dev_->get_extrinsics(rs::stream::rectified_color, rs::stream::color);
rs::intrinsics unrect_intrin = dev_->get_stream_intrinsics(rs::stream::color);
rsRectificationTable_ = compute_rectification_table(color_intrin, rect_to_unrect, unrect_intrin);
}
else if(rgbSource_ == kFishEye)
{
UINFO("calibration folder=%s name=%s", calibrationFolder.c_str(), cameraName.c_str());
if(!calibrationFolder.empty() && !cameraName.empty())
{
CameraModel model;
if(!model.load(calibrationFolder, cameraName))
{
UWARN("Failed to load calibration \"%s\" in \"%s\" folder, you should calibrate the camera!",
cameraName.c_str(), calibrationFolder.c_str());
}
else
{
UINFO("Camera parameters: fx=%f fy=%f cx=%f cy=%f",
model.fx(),
model.fy(),
model.cx(),
model.cy());
cameraModel_ = model;
cameraModel_.setName(cameraName);
cameraModel_.initRectificationMap();
cameraModel_.setLocalTransform(this->getLocalTransform()*imu2Camera);
}
}
}
uSleep(1000); // ignore the first frames uSleep(1000); // ignore the first frames
UINFO("Enabling streams...done!"); UINFO("Enabling streams...done!");
@@ -3073,8 +3415,23 @@ SensorData CameraRealSense::captureImage(CameraInfo * info)
// Retrieve camera parameters for mapping between depth and color // Retrieve camera parameters for mapping between depth and color
rs::intrinsics depth_intrin = dev_->get_stream_intrinsics(rs::stream::depth); rs::intrinsics depth_intrin = dev_->get_stream_intrinsics(rs::stream::depth);
rs::extrinsics depth_to_color = dev_->get_extrinsics(rs::stream::depth, rs::stream::color); rs::extrinsics depth_to_color;
rs::intrinsics color_intrin = dev_->get_stream_intrinsics(rs::stream::color); rs::intrinsics color_intrin;
if(rgbSource_ == kFishEye)
{
depth_to_color = dev_->get_extrinsics(rs::stream::depth, rs::stream::fisheye);
color_intrin = dev_->get_stream_intrinsics(rs::stream::fisheye);
}
else if(rgbSource_ == kInfrared)
{
depth_to_color = dev_->get_extrinsics(rs::stream::depth, rs::stream::infrared);
color_intrin = dev_->get_stream_intrinsics(rs::stream::infrared);
}
else // color
{
depth_to_color = dev_->get_extrinsics(rs::stream::depth, rs::stream::rectified_color);
color_intrin = dev_->get_stream_intrinsics(rs::stream::rectified_color);
}
#ifdef RTABMAP_REALSENSE_SLAM #ifdef RTABMAP_REALSENSE_SLAM
if(!dataReady_.acquire(1, 5000)) if(!dataReady_.acquire(1, 5000))
@@ -3082,6 +3439,7 @@ SensorData CameraRealSense::captureImage(CameraInfo * info)
UWARN("Not received new frames since 5 seconds, end of stream reached!"); UWARN("Not received new frames since 5 seconds, end of stream reached!");
return data; return data;
} }
{ {
UScopeMutex lock(dataMutex_); UScopeMutex lock(dataMutex_);
rgb = lastSyncFrames_.first; rgb = lastSyncFrames_.first;
@@ -3106,84 +3464,124 @@ SensorData CameraRealSense::captureImage(CameraInfo * info)
// Retrieve our images // Retrieve our images
depthIn = cv::Mat(depth_intrin.height, depth_intrin.width, CV_16UC1, (unsigned char*)dev_->get_frame_data(rs::stream::depth)); depthIn = cv::Mat(depth_intrin.height, depth_intrin.width, CV_16UC1, (unsigned char*)dev_->get_frame_data(rs::stream::depth));
rgb = cv::Mat(color_intrin.height, color_intrin.width, CV_8UC3, (unsigned char*)dev_->get_frame_data(rs::stream::color)); if(rgbSource_ == kFishEye)
#endif
float scale = dev_->get_depth_scale();
// factory registration...
cv::Mat bgr;
cv::cvtColor(rgb, bgr, CV_RGB2BGR);
CameraModel model(
color_intrin.fx, //fx
color_intrin.fy, //fy
color_intrin.ppx, //cx
color_intrin.ppy, //cy
this->getLocalTransform(),
0,
bgr.size());
cv::Mat depth;
if (color_intrin.width % depth_intrin.width == 0 && color_intrin.height % depth_intrin.height == 0 &&
depth_intrin.width < color_intrin.width &&
depth_intrin.height < color_intrin.height &&
!depthScaledToRGBSize_)
{ {
//we can keep the depth image size as is rgb = cv::Mat(color_intrin.height, color_intrin.width, CV_8UC1, (unsigned char*)dev_->get_frame_data(rs::stream::fisheye));
depth = cv::Mat::zeros(cv::Size(depth_intrin.width, depth_intrin.height), CV_16UC1); }
float scaleX = float(depth_intrin.width) / float(color_intrin.width); else if(rgbSource_ == kInfrared)
float scaleY = float(depth_intrin.height) / float(color_intrin.height); {
color_intrin.fx *= scaleX; rgb = cv::Mat(color_intrin.height, color_intrin.width, CV_8UC1, (unsigned char*)dev_->get_frame_data(rs::stream::infrared));
color_intrin.fy *= scaleY;
color_intrin.ppx *= scaleX;
color_intrin.ppy *= scaleY;
color_intrin.height = depth_intrin.height;
color_intrin.width = depth_intrin.width;
} }
else else
{ {
//depth to color rgb = cv::Mat(color_intrin.height, color_intrin.width, CV_8UC3, (unsigned char*)dev_->get_frame_data(rs::stream::color));
depth = cv::Mat::zeros(bgr.size(), CV_16UC1);
} }
for (int dy = 0; dy < depth_intrin.height; ++dy) #endif
// factory registration...
cv::Mat bgr;
if(rgbSource_ != kColor)
{ {
for (int dx = 0; dx < depth_intrin.width; ++dx) bgr = rgb;
}
else
{
cv::cvtColor(rgb, bgr, CV_RGB2BGR);
}
bool rectified = false;
if(rgbSource_ == kFishEye && cameraModel_.isRectificationMapInitialized())
{
bgr = cameraModel_.rectifyImage(bgr);
rectified = true;
color_intrin.fx = cameraModel_.fx();
color_intrin.fy = cameraModel_.fy();
color_intrin.ppx = cameraModel_.cx();
color_intrin.ppy = cameraModel_.cy();
UASSERT_MSG(color_intrin.width == cameraModel_.imageWidth() && color_intrin.height == cameraModel_.imageHeight(),
uFormat("color_intrin=%dx%d cameraModel_=%dx%d",
color_intrin.width, color_intrin.height, cameraModel_.imageWidth(), cameraModel_.imageHeight()).c_str());
((rs_intrinsics*)&color_intrin)->model = RS_DISTORTION_NONE;
}
#ifndef RTABMAP_REALSENSE_SLAM
else if(rgbSource_ != kColor)
{
bgr = bgr.clone();
}
#endif
cv::Mat depth;
if(rgbSource_ != kFishEye || rectified)
{
if (color_intrin.width % depth_intrin.width == 0 && color_intrin.height % depth_intrin.height == 0 &&
depth_intrin.width < color_intrin.width &&
depth_intrin.height < color_intrin.height &&
!depthScaledToRGBSize_)
{ {
// Retrieve the 16-bit depth value and map it into a depth in meters //we can keep the depth image size as is
uint16_t depth_value = depthIn.at<unsigned short>(dy,dx); depth = cv::Mat::zeros(cv::Size(depth_intrin.width, depth_intrin.height), CV_16UC1);
float depth_in_meters = depth_value * scale; float scaleX = float(depth_intrin.width) / float(color_intrin.width);
float scaleY = float(depth_intrin.height) / float(color_intrin.height);
color_intrin.fx *= scaleX;
color_intrin.fy *= scaleY;
color_intrin.ppx *= scaleX;
color_intrin.ppy *= scaleY;
color_intrin.height = depth_intrin.height;
color_intrin.width = depth_intrin.width;
}
else
{
//depth to color
depth = cv::Mat::zeros(bgr.size(), CV_16UC1);
}
// Skip over pixels with a depth value of zero, which is used to indicate no data float scale = dev_->get_depth_scale();
if (depth_value == 0 || depth_in_meters>10.0f) continue; for (int dy = 0; dy < depth_intrin.height; ++dy)
{
// Map from pixel coordinates in the depth image to pixel coordinates in the color image for (int dx = 0; dx < depth_intrin.width; ++dx)
rs::float2 depth_pixel = { (float)dx, (float)dy };
rs::float3 depth_point = depth_intrin.deproject(depth_pixel, depth_in_meters);
rs::float3 color_point = depth_to_color.transform(depth_point);
rs::float2 color_pixel = color_intrin.project(color_point);
int pdx = color_pixel.x;
int pdy = color_pixel.y;
if (uIsInBounds(pdx, 0, depth.cols) && uIsInBounds(pdy, 0, depth.rows))
{ {
depth.at<unsigned short>(pdy, pdx) = (unsigned short)(depth_in_meters*1000.0f); // convert to mm // Retrieve the 16-bit depth value and map it into a depth in meters
uint16_t depth_value = depthIn.at<unsigned short>(dy,dx);
float depth_in_meters = depth_value * scale;
// Skip over pixels with a depth value of zero, which is used to indicate no data
if (depth_value == 0 || depth_in_meters>10.0f) continue;
// Map from pixel coordinates in the depth image to pixel coordinates in the color image
int pdx = dx;
int pdy = dy;
if(rgbSource_ == kColor || rgbSource_ == kFishEye)
{
rs::float2 depth_pixel = { (float)dx, (float)dy };
rs::float3 depth_point = depth_intrin.deproject(depth_pixel, depth_in_meters);
rs::float3 color_point = depth_to_color.transform(depth_point);
rs::float2 color_pixel = color_intrin.project(color_point);
pdx = color_pixel.x;
pdy = color_pixel.y;
}
//else infrared is already registered
if (uIsInBounds(pdx, 0, depth.cols) && uIsInBounds(pdy, 0, depth.rows))
{
depth.at<unsigned short>(pdy, pdx) = (unsigned short)(depth_in_meters*1000.0f); // convert to mm
}
} }
} }
if (color_intrin.width > depth_intrin.width)
{
// Fill holes
UTimer time;
util2d::fillRegisteredDepthHoles(depth, true, true, color_intrin.width > depth_intrin.width * 2);
util2d::fillRegisteredDepthHoles(depth, true, true, color_intrin.width > depth_intrin.width * 2);//second pass
UDEBUG("Filling depth holes: %fs", time.ticks());
}
} }
if (color_intrin.width > depth_intrin.width) if (!bgr.empty() && ((rgbSource_==kFishEye && !rectified) || !depth.empty()))
{ {
// Fill holes data = SensorData(bgr, depth, cameraModel_, this->getNextSeqID(), UTimer::now());
UTimer time;
util2d::fillRegisteredDepthHoles(depth, true, true, color_intrin.width > depth_intrin.width * 2);
util2d::fillRegisteredDepthHoles(depth, true, true, color_intrin.width > depth_intrin.width * 2);//second pass
UDEBUG("Filling depth holes: %fs", time.ticks());
}
if (!bgr.empty() && !depth.empty())
{
data = SensorData(bgr, depth, model, this->getNextSeqID(), UTimer::now());
#ifdef RTABMAP_REALSENSE_SLAM #ifdef RTABMAP_REALSENSE_SLAM
if(info && slam_) if(info && slam_)
{ {
@@ -3191,8 +3589,20 @@ SensorData CameraRealSense::captureImage(CameraInfo * info)
rs::slam::PoseMatrix4f pose; rs::slam::PoseMatrix4f pose;
if(slam_->get_camera_pose(pose) == rs::core::status_no_error) if(slam_->get_camera_pose(pose) == rs::core::status_no_error)
{ {
Transform opticalRotation(0,0,1,0, -1,0,0,0, 0,-1,0,0); /*rs::slam::tracking_accuracy accuracy = slam_->get_tracking_accuracy();
info->odomPose = opticalRotation * rsPoseToTransform(pose) * opticalRotation.inverse(); if( accuracy == rs::slam::tracking_accuracy::low ||
accuracy == rs::slam::tracking_accuracy::medium ||
accuracy == rs::slam::tracking_accuracy::high)*/
{
// the pose is in camera link or IMU frame, get pose of the color camera
Transform opticalRotation(0,0,1,0, -1,0,0,0, 0,-1,0,0);
info->odomPose = opticalRotation * rsPoseToTransform(pose) * opticalRotation.inverse();
info->odomCovariance = cv::Mat::eye(6, 6, CV_64FC1) * 0.0005;
}
/*else
{
UERROR("Odometry failed: accuracy=%d", accuracy);
}*/
} }
else else
{ {

View File

@@ -3822,7 +3822,7 @@ Signature * Memory::createSignature(const SensorData & inputData, const Transfor
} }
cv::Mat depthMask; cv::Mat depthMask;
if(!decimatedData.depthRaw().empty() && _depthAsMask) if(imagesRectified && !decimatedData.depthRaw().empty() && _depthAsMask)
{ {
if(imageMono.rows % decimatedData.depthRaw().rows == 0 && if(imageMono.rows % decimatedData.depthRaw().rows == 0 &&
imageMono.cols % decimatedData.depthRaw().cols == 0 && imageMono.cols % decimatedData.depthRaw().cols == 0 &&

View File

@@ -630,6 +630,7 @@ void CalibrationDialog::restart()
maxIrs_[1] = 0x7fff; maxIrs_[1] = 0x7fff;
ui_->pushButton_calibrate->setEnabled(ui_->checkBox_unlock->isChecked()); ui_->pushButton_calibrate->setEnabled(ui_->checkBox_unlock->isChecked());
ui_->checkBox_fisheye->setEnabled(ui_->checkBox_unlock->isChecked());
ui_->pushButton_save->setEnabled(false); ui_->pushButton_save->setEnabled(false);
ui_->radioButton_raw->setChecked(true); ui_->radioButton_raw->setChecked(true);
ui_->radioButton_rectified->setEnabled(false); ui_->radioButton_rectified->setEnabled(false);
@@ -673,6 +674,7 @@ void CalibrationDialog::restart()
void CalibrationDialog::unlock() void CalibrationDialog::unlock()
{ {
ui_->pushButton_calibrate->setEnabled(true); ui_->pushButton_calibrate->setEnabled(true);
ui_->checkBox_fisheye->setEnabled(true);
} }
void CalibrationDialog::calibrate() void CalibrationDialog::calibrate()
@@ -715,13 +717,26 @@ void CalibrationDialog::calibrate()
if(fishEye) if(fishEye)
{ {
rms = cv::fisheye::calibrate(objectPoints, try
imagePoints_[id], {
imageSize_[id], rms = cv::fisheye::calibrate(objectPoints,
K, imagePoints_[id],
D, imageSize_[id],
rvecs, K,
tvecs); D,
rvecs,
tvecs,
cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC |
cv::fisheye::CALIB_CHECK_COND |
cv::fisheye::CALIB_FIX_SKEW);
}
catch(const cv::Exception & e)
{
UERROR("Error: %s (try restarting the calibration)", e.what());
QMessageBox::warning(this, tr("Calibration failed!"), tr("Error: %1 (try restarting the calibration)").arg(e.what()));
processingData_ = false;
return;
}
} }
else else
#endif #endif
@@ -748,7 +763,7 @@ void CalibrationDialog::calibrate()
#if CV_MAJOR_VERSION > 2 or (CV_MAJOR_VERSION == 2 and (CV_MINOR_VERSION >4 or (CV_MINOR_VERSION == 4 and CV_SUBMINOR_VERSION >=10))) #if CV_MAJOR_VERSION > 2 or (CV_MAJOR_VERSION == 2 and (CV_MINOR_VERSION >4 or (CV_MINOR_VERSION == 4 and CV_SUBMINOR_VERSION >=10)))
if(fishEye) if(fishEye)
{ {
cv::fisheye::projectPoints( cv::Mat(objectPoints[i]), rvecs[i], tvecs[i], K, D, imagePoints2); cv::fisheye::projectPoints( cv::Mat(objectPoints[i]), imagePoints2, rvecs[i], tvecs[i], K, D);
} }
else else
#endif #endif
@@ -1066,8 +1081,7 @@ bool CalibrationDialog::save()
else else
{ {
UASSERT(stereoModel_.left().isValidForRectification() && UASSERT(stereoModel_.left().isValidForRectification() &&
stereoModel_.right().isValidForRectification() && stereoModel_.right().isValidForRectification());
(!ui_->label_baseline->isVisible() || stereoModel_.baseline() > 0.0));
QString cameraName = stereoModel_.name().c_str(); QString cameraName = stereoModel_.name().c_str();
QString filePath = QFileDialog::getSaveFileName(this, tr("Export"), savingDirectory_ + "/" + cameraName, "*.yaml"); QString filePath = QFileDialog::getSaveFileName(this, tr("Export"), savingDirectory_ + "/" + cameraName, "*.yaml");
QString name = QFileInfo(filePath).baseName(); QString name = QFileInfo(filePath).baseName();

View File

@@ -574,6 +574,7 @@ PreferencesDialog::PreferencesDialog(QWidget * parent) :
connect(_ui->comboBox_realsensePresetDepth, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->comboBox_realsensePresetDepth, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_realsenseOdom, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->checkbox_realsenseOdom, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_realsenseDepthScaledToRGBSize, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->checkbox_realsenseDepthScaledToRGBSize, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->comboBox_realsenseRGBSource, SIGNAL(currentIndexChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_rs2_emitter, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->checkbox_rs2_emitter, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
connect(_ui->checkbox_rs2_irDepth, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel())); connect(_ui->checkbox_rs2_irDepth, SIGNAL(stateChanged(int)), this, SLOT(makeObsoleteSourcePanel()));
@@ -1662,6 +1663,7 @@ void PreferencesDialog::resetSettings(QGroupBox * groupBox)
_ui->comboBox_realsensePresetDepth->setCurrentIndex(2); _ui->comboBox_realsensePresetDepth->setCurrentIndex(2);
_ui->checkbox_realsenseOdom->setChecked(false); _ui->checkbox_realsenseOdom->setChecked(false);
_ui->checkbox_realsenseDepthScaledToRGBSize->setChecked(false); _ui->checkbox_realsenseDepthScaledToRGBSize->setChecked(false);
_ui->comboBox_realsenseRGBSource->setCurrentIndex(0);
_ui->checkbox_rs2_emitter->setChecked(true); _ui->checkbox_rs2_emitter->setChecked(true);
_ui->checkbox_rs2_irDepth->setChecked(false); _ui->checkbox_rs2_irDepth->setChecked(false);
_ui->lineEdit_openniOniPath->clear(); _ui->lineEdit_openniOniPath->clear();
@@ -2061,6 +2063,7 @@ void PreferencesDialog::readCameraSettings(const QString & filePath)
_ui->comboBox_realsensePresetDepth->setCurrentIndex(settings.value("presetDepth", _ui->comboBox_realsensePresetDepth->currentIndex()).toInt()); _ui->comboBox_realsensePresetDepth->setCurrentIndex(settings.value("presetDepth", _ui->comboBox_realsensePresetDepth->currentIndex()).toInt());
_ui->checkbox_realsenseOdom->setChecked(settings.value("odom", _ui->checkbox_realsenseOdom->isChecked()).toBool()); _ui->checkbox_realsenseOdom->setChecked(settings.value("odom", _ui->checkbox_realsenseOdom->isChecked()).toBool());
_ui->checkbox_realsenseDepthScaledToRGBSize->setChecked(settings.value("depthScaled", _ui->checkbox_realsenseDepthScaledToRGBSize->isChecked()).toBool()); _ui->checkbox_realsenseDepthScaledToRGBSize->setChecked(settings.value("depthScaled", _ui->checkbox_realsenseDepthScaledToRGBSize->isChecked()).toBool());
_ui->comboBox_realsenseRGBSource->setCurrentIndex(settings.value("rgbSource", _ui->comboBox_realsenseRGBSource->currentIndex()).toInt());
settings.endGroup(); // RealSense settings.endGroup(); // RealSense
settings.beginGroup("RealSense2"); settings.beginGroup("RealSense2");
@@ -2484,6 +2487,7 @@ void PreferencesDialog::writeCameraSettings(const QString & filePath) const
settings.setValue("presetDepth", _ui->comboBox_realsensePresetDepth->currentIndex()); settings.setValue("presetDepth", _ui->comboBox_realsensePresetDepth->currentIndex());
settings.setValue("odom", _ui->checkbox_realsenseOdom->isChecked()); settings.setValue("odom", _ui->checkbox_realsenseOdom->isChecked());
settings.setValue("depthScaled", _ui->checkbox_realsenseDepthScaledToRGBSize->isChecked()); settings.setValue("depthScaled", _ui->checkbox_realsenseDepthScaledToRGBSize->isChecked());
settings.setValue("rgbSource", _ui->comboBox_realsenseRGBSource->currentIndex());
settings.endGroup(); // RealSense settings.endGroup(); // RealSense
settings.beginGroup("RealSense2"); settings.beginGroup("RealSense2");
@@ -5021,10 +5025,10 @@ Camera * PreferencesDialog::createCamera(bool useRawImages, bool useColor)
} }
else if (driver == kSrcRealSense) else if (driver == kSrcRealSense)
{ {
if(useRawImages) if(useRawImages && _ui->comboBox_realsenseRGBSource->currentIndex()!=2)
{ {
QMessageBox::warning(this, tr("Calibration"), QMessageBox::warning(this, tr("Calibration"),
tr("Using raw images for \"RealSense\" driver is not yet supported. " tr("Using raw images for \"RealSense\" driver is not yet supported for color and infrared streams. "
"Factory calibration loaded from RealSense is used."), QMessageBox::Ok); "Factory calibration loaded from RealSense is used."), QMessageBox::Ok);
return 0; return 0;
} }
@@ -5038,6 +5042,7 @@ Camera * PreferencesDialog::createCamera(bool useRawImages, bool useColor)
this->getGeneralInputRate(), this->getGeneralInputRate(),
this->getSourceLocalTransform()); this->getSourceLocalTransform());
((CameraRealSense*)camera)->setDepthScaledToRGBSize(_ui->checkbox_realsenseDepthScaledToRGBSize->isChecked()); ((CameraRealSense*)camera)->setDepthScaledToRGBSize(_ui->checkbox_realsenseDepthScaledToRGBSize->isChecked());
((CameraRealSense*)camera)->setRGBSource((CameraRealSense::RGBSource)_ui->comboBox_realsenseRGBSource->currentIndex());
} }
} }
else if (driver == kSrcRealSense2) else if (driver == kSrcRealSense2)
@@ -5824,7 +5829,7 @@ void PreferencesDialog::calibrate()
} }
bool freenect2 = driver == kSrcFreenect2; bool freenect2 = driver == kSrcFreenect2;
_calibrationDialog->setStereoMode(this->getSourceType() != kSrcRGB, freenect2?"rgb":"left", freenect2?"depth":"right"); // RGB+Depth or left+right _calibrationDialog->setStereoMode(this->getSourceType() != kSrcRGB && driver != kSrcRealSense, freenect2?"rgb":"left", freenect2?"depth":"right"); // RGB+Depth or left+right
_calibrationDialog->setSwitchedImages(freenect2); _calibrationDialog->setSwitchedImages(freenect2);
_calibrationDialog->setSavingDirectory(this->getCameraInfoDir()); _calibrationDialog->setSavingDirectory(this->getCameraInfoDir());
_calibrationDialog->registerToEventsManager(); _calibrationDialog->registerToEventsManager();

View File

@@ -94,8 +94,8 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>-287</y>
<width>678</width> <width>681</width>
<height>2943</height> <height>2943</height>
</rect> </rect>
</property> </property>
@@ -117,7 +117,7 @@
<enum>QFrame::Raised</enum> <enum>QFrame::Raised</enum>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>7</number> <number>5</number>
</property> </property>
<widget class="QWidget" name="page_22"> <widget class="QWidget" name="page_22">
<layout class="QVBoxLayout" name="verticalLayout_29" stretch="0,1"> <layout class="QVBoxLayout" name="verticalLayout_29" stretch="0,1">
@@ -3600,7 +3600,7 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
<string>RealSense</string> <string>RealSense</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_73" columnstretch="0,1"> <layout class="QGridLayout" name="gridLayout_73" columnstretch="0,1">
<item row="4" column="0"> <item row="5" column="0">
<spacer name="verticalSpacer_51"> <spacer name="verticalSpacer_51">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
@@ -3706,6 +3706,16 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0">
<widget class="QCheckBox" name="checkbox_realsenseDepthScaledToRGBSize">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="1"> <item row="3" column="1">
<widget class="QLabel" name="label_realsenseOdom_2"> <widget class="QLabel" name="label_realsenseOdom_2">
<property name="text"> <property name="text">
@@ -3719,13 +3729,38 @@ when using the file type, logs are saved in LogRtabmap.txt (located in the worki
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="4" column="0">
<widget class="QCheckBox" name="checkbox_realsenseDepthScaledToRGBSize"> <widget class="QComboBox" name="comboBox_realsenseRGBSource">
<property name="text"> <property name="sizeAdjustPolicy">
<string/> <enum>QComboBox::AdjustToContents</enum>
</property> </property>
<property name="checked"> <item>
<bool>false</bool> <property name="text">
<string>Color</string>
</property>
</item>
<item>
<property name="text">
<string>Infrared</string>
</property>
</item>
<item>
<property name="text">
<string>Fisheye</string>
</property>
</item>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_realsenseOdom_3">
<property name="text">
<string>RGB camera source. For fisheye has depth available only if it is calibrated.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property> </property>
</widget> </widget>
</item> </item>