mirror of
https://github.com/introlab/rtabmap.git
synced 2026-10-04 09:07:47 +08:00
Tango: added fisheye option
This commit is contained in:
+1
-6
@@ -43,12 +43,7 @@ ENDIF(${CMAKE_GENERATOR} MATCHES ".*Makefiles")
|
|||||||
|
|
||||||
IF(NOT ANDROID)
|
IF(NOT ANDROID)
|
||||||
SET(CMAKE_DEBUG_POSTFIX "d")
|
SET(CMAKE_DEBUG_POSTFIX "d")
|
||||||
ELSE()
|
ENDIF(NOT ANDROID)
|
||||||
option(DISABLE_LOG "Disable Android logging (should be true in release)" ON)
|
|
||||||
IF(DISABLE_LOG)
|
|
||||||
ADD_DEFINITIONS(-DDISABLE_LOG)
|
|
||||||
ENDIF(DISABLE_LOG)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
IF(WIN32 AND NOT MINGW)
|
IF(WIN32 AND NOT MINGW)
|
||||||
ADD_DEFINITIONS("-DNOMINMAX")
|
ADD_DEFINITIONS("-DNOMINMAX")
|
||||||
|
|||||||
@@ -1,4 +1,15 @@
|
|||||||
|
|
||||||
|
option(DISABLE_LOG "Disable Android logging (should be true in release)" ON)
|
||||||
|
IF(DISABLE_LOG)
|
||||||
|
ADD_DEFINITIONS(-DDISABLE_LOG)
|
||||||
|
ENDIF(DISABLE_LOG)
|
||||||
|
|
||||||
|
IF(DISABLE_LOG)
|
||||||
|
SET(ANDROID_DEBUGGABLE false)
|
||||||
|
ELSE()
|
||||||
|
SET(ANDROID_DEBUGGABLE true)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
add_subdirectory(jni)
|
add_subdirectory(jni)
|
||||||
|
|
||||||
|
|
||||||
@@ -6,12 +17,6 @@ add_subdirectory(jni)
|
|||||||
# Packaging
|
# Packaging
|
||||||
######
|
######
|
||||||
|
|
||||||
IF(DISABLE_LOG)
|
|
||||||
SET(ANDROID_DEBUGGABLE false)
|
|
||||||
ELSE()
|
|
||||||
SET(ANDROID_DEBUGGABLE true)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
# find android
|
# find android
|
||||||
find_host_program(ANDROID_EXECUTABLE
|
find_host_program(ANDROID_EXECUTABLE
|
||||||
NAMES android
|
NAMES android
|
||||||
|
|||||||
+142
-19
@@ -68,6 +68,10 @@ void onFrameAvailableRouter(void* context, TangoCameraId id, const TangoImageBuf
|
|||||||
{
|
{
|
||||||
tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
|
tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
|
||||||
}
|
}
|
||||||
|
else if(color->format == 35)
|
||||||
|
{
|
||||||
|
tangoImage = cv::Mat(color->height+color->height/2, color->width, CV_8UC1, color->data);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOGE("Not supported color format : %d.", color->format);
|
LOGE("Not supported color format : %d.", color->format);
|
||||||
@@ -100,11 +104,12 @@ void onTangoEventAvailableRouter(void* context, const TangoEvent* event)
|
|||||||
const float CameraTango::bilateralFilteringSigmaS = 2.0f;
|
const float CameraTango::bilateralFilteringSigmaS = 2.0f;
|
||||||
const float CameraTango::bilateralFilteringSigmaR = 0.075f;
|
const float CameraTango::bilateralFilteringSigmaR = 0.075f;
|
||||||
|
|
||||||
CameraTango::CameraTango(int decimation, bool autoExposure, bool publishRawScan, bool smoothing) :
|
CameraTango::CameraTango(bool colorCamera, int decimation, bool autoExposure, bool publishRawScan, bool smoothing) :
|
||||||
Camera(0),
|
Camera(0),
|
||||||
tango_config_(0),
|
tango_config_(0),
|
||||||
firstFrame_(true),
|
firstFrame_(true),
|
||||||
stampEpochOffset_(0.0),
|
stampEpochOffset_(0.0),
|
||||||
|
colorCamera_(colorCamera),
|
||||||
decimation_(decimation),
|
decimation_(decimation),
|
||||||
autoExposure_(autoExposure),
|
autoExposure_(autoExposure),
|
||||||
rawScanPublished_(publishRawScan),
|
rawScanPublished_(publishRawScan),
|
||||||
@@ -122,6 +127,65 @@ CameraTango::~CameraTango() {
|
|||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compute fisheye distorted coordinates from undistorted coordinates.
|
||||||
|
// The distortion model used by the Tango fisheye camera is called FOV and is
|
||||||
|
// described in 'Straight lines have to be straight' by Frederic Devernay and
|
||||||
|
// Olivier Faugeras. See https://hal.inria.fr/inria-00267247/document.
|
||||||
|
// Tango ROS Streamer: https://github.com/Intermodalics/tango_ros/blob/master/tango_ros_common/tango_ros_native/src/tango_ros_node.cpp
|
||||||
|
void applyFovModel(
|
||||||
|
double xu, double yu, double w, double w_inverse, double two_tan_w_div_two,
|
||||||
|
double* xd, double* yd) {
|
||||||
|
double ru = sqrt(xu * xu + yu * yu);
|
||||||
|
constexpr double epsilon = 1e-7;
|
||||||
|
if (w < epsilon || ru < epsilon) {
|
||||||
|
*xd = xu;
|
||||||
|
*yd = yu ;
|
||||||
|
} else {
|
||||||
|
double rd_div_ru = std::atan(ru * two_tan_w_div_two) * w_inverse / ru;
|
||||||
|
*xd = xu * rd_div_ru;
|
||||||
|
*yd = yu * rd_div_ru;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Compute the warp maps to undistort the Tango fisheye image using the FOV
|
||||||
|
// model. See OpenCV documentation for more information on warp maps:
|
||||||
|
// http://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html
|
||||||
|
// Tango ROS Streamer: https://github.com/Intermodalics/tango_ros/blob/master/tango_ros_common/tango_ros_native/src/tango_ros_node.cpp
|
||||||
|
// @param fisheyeModel the fisheye camera intrinsics.
|
||||||
|
// @param mapX the output map for the x direction.
|
||||||
|
// @param mapY the output map for the y direction.
|
||||||
|
void initFisheyeRectificationMap(
|
||||||
|
const CameraModel& fisheyeModel,
|
||||||
|
cv::Mat & mapX, cv::Mat & mapY) {
|
||||||
|
const double & fx = fisheyeModel.K().at<double>(0,0);
|
||||||
|
const double & fy = fisheyeModel.K().at<double>(1,1);
|
||||||
|
const double & cx = fisheyeModel.K().at<double>(0,2);
|
||||||
|
const double & cy = fisheyeModel.K().at<double>(1,2);
|
||||||
|
const double & w = fisheyeModel.D().at<double>(0,0);
|
||||||
|
mapX.create(fisheyeModel.imageSize(), CV_32FC1);
|
||||||
|
mapY.create(fisheyeModel.imageSize(), CV_32FC1);
|
||||||
|
LOGD("initFisheyeRectificationMap: fx=%f fy=%f, cx=%f, cy=%f, w=%f", fx, fy, cx, cy, w);
|
||||||
|
// Pre-computed variables for more efficiency.
|
||||||
|
const double fy_inverse = 1.0 / fy;
|
||||||
|
const double fx_inverse = 1.0 / fx;
|
||||||
|
const double w_inverse = 1 / w;
|
||||||
|
const double two_tan_w_div_two = 2.0 * std::tan(w * 0.5);
|
||||||
|
// Compute warp maps in x and y directions.
|
||||||
|
// OpenCV expects maps from dest to src, i.e. from undistorted to distorted
|
||||||
|
// pixel coordinates.
|
||||||
|
for(int iu = 0; iu < fisheyeModel.imageHeight(); ++iu) {
|
||||||
|
for (int ju = 0; ju < fisheyeModel.imageWidth(); ++ju) {
|
||||||
|
double xu = (ju - cx) * fx_inverse;
|
||||||
|
double yu = (iu - cy) * fy_inverse;
|
||||||
|
double xd, yd;
|
||||||
|
applyFovModel(xu, yu, w, w_inverse, two_tan_w_div_two, &xd, &yd);
|
||||||
|
double jd = cx + xd * fx;
|
||||||
|
double id = cy + yd * fy;
|
||||||
|
mapX.at<float>(iu, ju) = jd;
|
||||||
|
mapY.at<float>(iu, ju) = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool CameraTango::init(const std::string & calibrationFolder, const std::string & cameraName)
|
bool CameraTango::init(const std::string & calibrationFolder, const std::string & cameraName)
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
@@ -146,6 +210,8 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(colorCamera_)
|
||||||
|
{
|
||||||
// Enable color.
|
// Enable color.
|
||||||
ret = TangoConfig_setBool(tango_config_, "config_enable_color_camera", true);
|
ret = TangoConfig_setBool(tango_config_, "config_enable_color_camera", true);
|
||||||
if (ret != TANGO_SUCCESS)
|
if (ret != TANGO_SUCCESS)
|
||||||
@@ -153,7 +219,6 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
|
|||||||
LOGE("NativeRTABMap: config_enable_color_camera() failed with error code: %d", ret);
|
LOGE("NativeRTABMap: config_enable_color_camera() failed with error code: %d", ret);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// disable auto exposure (disabled, seems broken on latest Tango releases)
|
// disable auto exposure (disabled, seems broken on latest Tango releases)
|
||||||
ret = TangoConfig_setBool(tango_config_, "config_color_mode_auto", autoExposure_);
|
ret = TangoConfig_setBool(tango_config_, "config_color_mode_auto", autoExposure_);
|
||||||
if (ret != TANGO_SUCCESS)
|
if (ret != TANGO_SUCCESS)
|
||||||
@@ -179,6 +244,7 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
|
|||||||
TangoConfig_getInt32( tango_config_, "config_color_exp", &verifyExp );
|
TangoConfig_getInt32( tango_config_, "config_color_exp", &verifyExp );
|
||||||
LOGI( "NativeRTABMap: config_color autoExposure=%s %d %d", verifyAutoExposureState?"On" : "Off", verifyIso, verifyExp );
|
LOGI( "NativeRTABMap: config_color autoExposure=%s %d %d", verifyAutoExposureState?"On" : "Off", verifyIso, verifyExp );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Enable depth.
|
// Enable depth.
|
||||||
ret = TangoConfig_setBool(tango_config_, "config_enable_depth", true);
|
ret = TangoConfig_setBool(tango_config_, "config_enable_depth", true);
|
||||||
@@ -242,7 +308,7 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = TangoService_connectOnFrameAvailable(TANGO_CAMERA_COLOR, this, onFrameAvailableRouter);
|
ret = TangoService_connectOnFrameAvailable(colorCamera_?TANGO_CAMERA_COLOR:TANGO_CAMERA_FISHEYE, this, onFrameAvailableRouter);
|
||||||
if (ret != TANGO_SUCCESS)
|
if (ret != TANGO_SUCCESS)
|
||||||
{
|
{
|
||||||
LOGE("NativeRTABMap: Failed to connect to color callback with error code: %d", ret);
|
LOGE("NativeRTABMap: Failed to connect to color callback with error code: %d", ret);
|
||||||
@@ -291,7 +357,7 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
|
|||||||
//
|
//
|
||||||
// Get color camera with respect to device transformation matrix.
|
// Get color camera with respect to device transformation matrix.
|
||||||
frame_pair.base = TANGO_COORDINATE_FRAME_DEVICE;
|
frame_pair.base = TANGO_COORDINATE_FRAME_DEVICE;
|
||||||
frame_pair.target = TANGO_COORDINATE_FRAME_CAMERA_COLOR;
|
frame_pair.target = colorCamera_?TANGO_COORDINATE_FRAME_CAMERA_COLOR:TANGO_COORDINATE_FRAME_CAMERA_FISHEYE;
|
||||||
ret = TangoService_getPoseAtTime(0.0, frame_pair, &pose_data);
|
ret = TangoService_getPoseAtTime(0.0, frame_pair, &pose_data);
|
||||||
if (ret != TANGO_SUCCESS)
|
if (ret != TANGO_SUCCESS)
|
||||||
{
|
{
|
||||||
@@ -309,22 +375,59 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
|
|||||||
|
|
||||||
// camera intrinsic
|
// camera intrinsic
|
||||||
TangoCameraIntrinsics color_camera_intrinsics;
|
TangoCameraIntrinsics color_camera_intrinsics;
|
||||||
ret = TangoService_getCameraIntrinsics(TANGO_CAMERA_COLOR, &color_camera_intrinsics);
|
ret = TangoService_getCameraIntrinsics(colorCamera_?TANGO_CAMERA_COLOR:TANGO_CAMERA_FISHEYE, &color_camera_intrinsics);
|
||||||
if (ret != TANGO_SUCCESS)
|
if (ret != TANGO_SUCCESS)
|
||||||
{
|
{
|
||||||
LOGE("NativeRTABMap: Failed to get the intrinsics for the color camera with error code: %d.", ret);
|
LOGE("NativeRTABMap: Failed to get the intrinsics for the color camera with error code: %d.", ret);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
model_ = CameraModel(
|
|
||||||
color_camera_intrinsics.fx,
|
|
||||||
color_camera_intrinsics.fy,
|
|
||||||
color_camera_intrinsics.cx,
|
|
||||||
color_camera_intrinsics.cy,
|
|
||||||
this->getLocalTransform());
|
|
||||||
model_.setImageSize(cv::Size(color_camera_intrinsics.width, color_camera_intrinsics.height));
|
|
||||||
|
|
||||||
// device to camera optical rotation in rtabmap frame
|
cv::Mat K = cv::Mat::eye(3, 3, CV_64FC1);
|
||||||
model_.setLocalTransform(tango_device_T_rtabmap_device.inverse()*deviceTColorCamera_);
|
K.at<double>(0,0) = color_camera_intrinsics.fx;
|
||||||
|
K.at<double>(1,1) = color_camera_intrinsics.fy;
|
||||||
|
K.at<double>(0,2) = color_camera_intrinsics.cx;
|
||||||
|
K.at<double>(1,2) = color_camera_intrinsics.cy;
|
||||||
|
cv::Mat D = cv::Mat::zeros(1, 5, CV_64FC1);
|
||||||
|
LOGD("Calibration type = %d", color_camera_intrinsics.calibration_type);
|
||||||
|
if(color_camera_intrinsics.calibration_type == TANGO_CALIBRATION_POLYNOMIAL_5_PARAMETERS ||
|
||||||
|
color_camera_intrinsics.calibration_type == TANGO_CALIBRATION_EQUIDISTANT)
|
||||||
|
{
|
||||||
|
D.at<double>(0,0) = color_camera_intrinsics.distortion[0];
|
||||||
|
D.at<double>(0,1) = color_camera_intrinsics.distortion[1];
|
||||||
|
D.at<double>(0,2) = color_camera_intrinsics.distortion[2];
|
||||||
|
D.at<double>(0,3) = color_camera_intrinsics.distortion[3];
|
||||||
|
D.at<double>(0,4) = color_camera_intrinsics.distortion[4];
|
||||||
|
}
|
||||||
|
else if(color_camera_intrinsics.calibration_type == TANGO_CALIBRATION_POLYNOMIAL_3_PARAMETERS)
|
||||||
|
{
|
||||||
|
D.at<double>(0,0) = color_camera_intrinsics.distortion[0];
|
||||||
|
D.at<double>(0,1) = color_camera_intrinsics.distortion[1];
|
||||||
|
D.at<double>(0,2) = 0.;
|
||||||
|
D.at<double>(0,3) = 0.;
|
||||||
|
D.at<double>(0,4) = color_camera_intrinsics.distortion[2];
|
||||||
|
}
|
||||||
|
else if(color_camera_intrinsics.calibration_type == TANGO_CALIBRATION_POLYNOMIAL_2_PARAMETERS)
|
||||||
|
{
|
||||||
|
D.at<double>(0,0) = color_camera_intrinsics.distortion[0];
|
||||||
|
D.at<double>(0,1) = color_camera_intrinsics.distortion[1];
|
||||||
|
D.at<double>(0,2) = 0.;
|
||||||
|
D.at<double>(0,3) = 0.;
|
||||||
|
D.at<double>(0,4) = 0.;
|
||||||
|
}
|
||||||
|
|
||||||
|
cv::Mat R = cv::Mat::eye(3, 3, CV_64FC1);
|
||||||
|
cv::Mat P;
|
||||||
|
|
||||||
|
LOGD("Distortion params: %f, %f, %f, %f, %f", D.at<double>(0,0), D.at<double>(0,1), D.at<double>(0,2), D.at<double>(0,3), D.at<double>(0,4));
|
||||||
|
model_ = CameraModel(colorCamera_?"color":"fisheye",
|
||||||
|
cv::Size(color_camera_intrinsics.width, color_camera_intrinsics.height),
|
||||||
|
K, D, R, P,
|
||||||
|
tango_device_T_rtabmap_device.inverse()*deviceTColorCamera_); // device to camera optical rotation in rtabmap frame
|
||||||
|
|
||||||
|
if(!colorCamera_)
|
||||||
|
{
|
||||||
|
initFisheyeRectificationMap(model_, fisheyeRectifyMapX_, fisheyeRectifyMapY_);
|
||||||
|
}
|
||||||
|
|
||||||
LOGI("deviceTColorCameraTango =%s", deviceTColorCamera_.prettyPrint().c_str());
|
LOGI("deviceTColorCameraTango =%s", deviceTColorCamera_.prettyPrint().c_str());
|
||||||
LOGI("deviceTColorCameraRtabmap=%s", (tango_device_T_rtabmap_device.inverse()*deviceTColorCamera_).prettyPrint().c_str());
|
LOGI("deviceTColorCameraRtabmap=%s", (tango_device_T_rtabmap_device.inverse()*deviceTColorCamera_).prettyPrint().c_str());
|
||||||
@@ -343,6 +446,8 @@ void CameraTango::close()
|
|||||||
TangoService_disconnect();
|
TangoService_disconnect();
|
||||||
}
|
}
|
||||||
firstFrame_ = true;
|
firstFrame_ = true;
|
||||||
|
fisheyeRectifyMapX_ = cv::Mat();
|
||||||
|
fisheyeRectifyMapY_ = cv::Mat();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraTango::cloudReceived(const cv::Mat & cloud, double timestamp)
|
void CameraTango::cloudReceived(const cv::Mat & cloud, double timestamp)
|
||||||
@@ -397,7 +502,7 @@ void CameraTango::rgbReceived(const cv::Mat & tangoImage, int type, double times
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static rtabmap::Transform opticalRotationTango(
|
static rtabmap::Transform opticalRotation(
|
||||||
1.0f, 0.0f, 0.0f, 0.0f,
|
1.0f, 0.0f, 0.0f, 0.0f,
|
||||||
0.0f, -1.0f, 0.0f, 0.0f,
|
0.0f, -1.0f, 0.0f, 0.0f,
|
||||||
0.0f, 0.0f, -1.0f, 0.0f);
|
0.0f, 0.0f, -1.0f, 0.0f);
|
||||||
@@ -406,7 +511,7 @@ void CameraTango::poseReceived(const Transform & pose)
|
|||||||
if(!pose.isNull() && pose.getNormSquared() < 100000)
|
if(!pose.isNull() && pose.getNormSquared() < 100000)
|
||||||
{
|
{
|
||||||
// send pose of the camera (without optical rotation), not the device
|
// send pose of the camera (without optical rotation), not the device
|
||||||
this->post(new PoseEvent(pose*deviceTColorCamera_*opticalRotationTango));
|
this->post(new PoseEvent(pose*deviceTColorCamera_*opticalRotation));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,6 +626,7 @@ SensorData CameraTango::captureImage(CameraInfo * info)
|
|||||||
tangoColorType_ = 0;
|
tangoColorType_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOGD("tangoColorType=%d", tangoColorType);
|
||||||
if(tangoColorType == TANGO_HAL_PIXEL_FORMAT_RGBA_8888)
|
if(tangoColorType == TANGO_HAL_PIXEL_FORMAT_RGBA_8888)
|
||||||
{
|
{
|
||||||
cv::cvtColor(tangoImage, rgb, CV_RGBA2BGR);
|
cv::cvtColor(tangoImage, rgb, CV_RGBA2BGR);
|
||||||
@@ -533,6 +639,10 @@ SensorData CameraTango::captureImage(CameraInfo * info)
|
|||||||
{
|
{
|
||||||
cv::cvtColor(tangoImage, rgb, CV_YUV2BGR_NV21);
|
cv::cvtColor(tangoImage, rgb, CV_YUV2BGR_NV21);
|
||||||
}
|
}
|
||||||
|
else if(tangoColorType == 35)
|
||||||
|
{
|
||||||
|
cv::cvtColor(tangoImage, rgb, cv::COLOR_YUV420sp2GRAY);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOGE("Not supported color format : %d.", tangoColorType);
|
LOGE("Not supported color format : %d.", tangoColorType);
|
||||||
@@ -545,11 +655,23 @@ SensorData CameraTango::captureImage(CameraInfo * info)
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
CameraModel model = model_;
|
CameraModel model = model_;
|
||||||
|
|
||||||
|
if(colorCamera_)
|
||||||
|
{
|
||||||
if(decimation_ > 1)
|
if(decimation_ > 1)
|
||||||
{
|
{
|
||||||
rgb = util2d::decimate(rgb, decimation_);
|
rgb = util2d::decimate(rgb, decimation_);
|
||||||
model = model.scaled(1.0/double(decimation_));
|
model = model.scaled(1.0/double(decimation_));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//UTimer t;
|
||||||
|
cv::Mat rgbRect;
|
||||||
|
cv::remap(rgb, rgbRect, fisheyeRectifyMapX_, fisheyeRectifyMapY_, cv::INTER_LINEAR, cv::BORDER_CONSTANT, 0);
|
||||||
|
rgb = rgbRect;
|
||||||
|
//LOGD("Rectification time=%fs", t.ticks());
|
||||||
|
}
|
||||||
|
|
||||||
// Querying the depth image's frame transformation based on the depth image's
|
// Querying the depth image's frame transformation based on the depth image's
|
||||||
// timestamp.
|
// timestamp.
|
||||||
@@ -561,7 +683,7 @@ SensorData CameraTango::captureImage(CameraInfo * info)
|
|||||||
Transform colorToDepth;
|
Transform colorToDepth;
|
||||||
TangoPoseData pose_color_image_t1_T_depth_image_t0;
|
TangoPoseData pose_color_image_t1_T_depth_image_t0;
|
||||||
if (TangoSupport_calculateRelativePose(
|
if (TangoSupport_calculateRelativePose(
|
||||||
rgbStamp, TANGO_COORDINATE_FRAME_CAMERA_COLOR, cloudStamp,
|
rgbStamp, colorCamera_?TANGO_COORDINATE_FRAME_CAMERA_COLOR:TANGO_COORDINATE_FRAME_CAMERA_FISHEYE, cloudStamp,
|
||||||
TANGO_COORDINATE_FRAME_CAMERA_DEPTH,
|
TANGO_COORDINATE_FRAME_CAMERA_DEPTH,
|
||||||
&pose_color_image_t1_T_depth_image_t0) == TANGO_SUCCESS)
|
&pose_color_image_t1_T_depth_image_t0) == TANGO_SUCCESS)
|
||||||
{
|
{
|
||||||
@@ -589,8 +711,9 @@ SensorData CameraTango::captureImage(CameraInfo * info)
|
|||||||
LOGD("rgb=%dx%d cloud size=%d", rgb.cols, rgb.rows, (int)cloud.total());
|
LOGD("rgb=%dx%d cloud size=%d", rgb.cols, rgb.rows, (int)cloud.total());
|
||||||
|
|
||||||
int pixelsSet = 0;
|
int pixelsSet = 0;
|
||||||
depth = cv::Mat::zeros(model_.imageHeight()/8, model_.imageWidth()/8, CV_16UC1); // mm
|
int depthSizeDec = colorCamera_?8:1;
|
||||||
CameraModel depthModel = model_.scaled(1.0f/8.0f);
|
depth = cv::Mat::zeros(model_.imageHeight()/depthSizeDec, model_.imageWidth()/depthSizeDec, CV_16UC1); // mm
|
||||||
|
CameraModel depthModel = model_.scaled(1.0f/float(depthSizeDec));
|
||||||
std::vector<cv::Point3f> scanData(rawScanPublished_?cloud.total():0);
|
std::vector<cv::Point3f> scanData(rawScanPublished_?cloud.total():0);
|
||||||
int oi=0;
|
int oi=0;
|
||||||
for(unsigned int i=0; i<cloud.total(); ++i)
|
for(unsigned int i=0; i<cloud.total(); ++i)
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public:
|
|||||||
static const float bilateralFilteringSigmaR;
|
static const float bilateralFilteringSigmaR;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CameraTango(int decimation, bool autoExposure, bool publishRawScan, bool smoothing);
|
CameraTango(bool colorCamera, int decimation, bool autoExposure, bool publishRawScan, bool smoothing);
|
||||||
virtual ~CameraTango();
|
virtual ~CameraTango();
|
||||||
|
|
||||||
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
|
||||||
@@ -84,6 +84,7 @@ public:
|
|||||||
virtual std::string getSerial() const;
|
virtual std::string getSerial() const;
|
||||||
const CameraModel & getCameraModel() const {return model_;}
|
const CameraModel & getCameraModel() const {return model_;}
|
||||||
rtabmap::Transform tangoPoseToTransform(const TangoPoseData * tangoPose) const;
|
rtabmap::Transform tangoPoseToTransform(const TangoPoseData * tangoPose) const;
|
||||||
|
void setColorCamera(bool enabled) {if(!this->isRunning()) colorCamera_ = enabled;}
|
||||||
void setDecimation(int value) {decimation_ = value;}
|
void setDecimation(int value) {decimation_ = value;}
|
||||||
void setSmoothing(bool enabled) {smoothing_ = enabled;}
|
void setSmoothing(bool enabled) {smoothing_ = enabled;}
|
||||||
void setAutoExposure(bool enabled) {autoExposure_ = enabled;}
|
void setAutoExposure(bool enabled) {autoExposure_ = enabled;}
|
||||||
@@ -109,6 +110,7 @@ private:
|
|||||||
bool firstFrame_;
|
bool firstFrame_;
|
||||||
UTimer cameraStartedTime_;
|
UTimer cameraStartedTime_;
|
||||||
double stampEpochOffset_;
|
double stampEpochOffset_;
|
||||||
|
bool colorCamera_;
|
||||||
int decimation_;
|
int decimation_;
|
||||||
bool autoExposure_;
|
bool autoExposure_;
|
||||||
bool rawScanPublished_;
|
bool rawScanPublished_;
|
||||||
@@ -123,6 +125,8 @@ private:
|
|||||||
CameraModel model_;
|
CameraModel model_;
|
||||||
Transform deviceTColorCamera_;
|
Transform deviceTColorCamera_;
|
||||||
TangoSupportRotation colorCameraToDisplayRotation_;
|
TangoSupportRotation colorCameraToDisplayRotation_;
|
||||||
|
cv::Mat fisheyeRectifyMapX_;
|
||||||
|
cv::Mat fisheyeRectifyMapY_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace rtabmap */
|
} /* namespace rtabmap */
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ rtabmap::ParametersMap RTABMapApp::getRtabmapParameters()
|
|||||||
|
|
||||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kKpMaxFeatures(), std::string("200")));
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kKpMaxFeatures(), std::string("200")));
|
||||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kGFTTQualityLevel(), std::string("0.0001")));
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kGFTTQualityLevel(), std::string("0.0001")));
|
||||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemImagePreDecimation(), std::string(fullResolution_?"2":"1")));
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kMemImagePreDecimation(), std::string(cameraColor_&&fullResolution_?"2":"1")));
|
||||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kBRIEFBytes(), std::string("64")));
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kBRIEFBytes(), std::string("64")));
|
||||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRtabmapTimeThr(), std::string("800")));
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRtabmapTimeThr(), std::string("800")));
|
||||||
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRtabmapPublishLikelihood(), std::string("false")));
|
parameters.insert(rtabmap::ParametersPair(rtabmap::Parameters::kRtabmapPublishLikelihood(), std::string("false")));
|
||||||
@@ -153,6 +153,7 @@ RTABMapApp::RTABMapApp() :
|
|||||||
autoExposure_(true),
|
autoExposure_(true),
|
||||||
rawScanSaved_(false),
|
rawScanSaved_(false),
|
||||||
smoothing_(true),
|
smoothing_(true),
|
||||||
|
cameraColor_(true),
|
||||||
fullResolution_(false),
|
fullResolution_(false),
|
||||||
appendMode_(true),
|
appendMode_(true),
|
||||||
maxCloudDepth_(0.0),
|
maxCloudDepth_(0.0),
|
||||||
@@ -257,13 +258,12 @@ void RTABMapApp::onCreate(JNIEnv* env, jobject caller_activity)
|
|||||||
|
|
||||||
this->registerToEventsManager();
|
this->registerToEventsManager();
|
||||||
|
|
||||||
camera_ = new rtabmap::CameraTango(fullResolution_?1:2, autoExposure_, rawScanSaved_, smoothing_);
|
camera_ = new rtabmap::CameraTango(cameraColor_, !cameraColor_ || fullResolution_?1:2, autoExposure_, rawScanSaved_, smoothing_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTABMapApp::setScreenRotation(int displayRotation, int cameraRotation)
|
void RTABMapApp::setScreenRotation(int displayRotation, int cameraRotation)
|
||||||
{
|
{
|
||||||
TangoSupportRotation rotation = tango_gl::util::GetAndroidRotationFromColorCameraToDisplay(
|
TangoSupportRotation rotation = tango_gl::util::GetAndroidRotationFromColorCameraToDisplay(displayRotation, cameraRotation);
|
||||||
displayRotation, cameraRotation);
|
|
||||||
LOGI("Set orientation: display=%d camera=%d -> %d", displayRotation, cameraRotation, (int)rotation);
|
LOGI("Set orientation: display=%d camera=%d -> %d", displayRotation, cameraRotation, (int)rotation);
|
||||||
main_scene_.setScreenRotation(rotation);
|
main_scene_.setScreenRotation(rotation);
|
||||||
camera_->setScreenRotation(rotation);
|
camera_->setScreenRotation(rotation);
|
||||||
@@ -458,6 +458,7 @@ bool RTABMapApp::onTangoServiceConnected(JNIEnv* env, jobject iBinder)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
camera_->setColorCamera(cameraColor_);
|
||||||
if(camera_->init())
|
if(camera_->init())
|
||||||
{
|
{
|
||||||
LOGI("Start camera thread");
|
LOGI("Start camera thread");
|
||||||
@@ -524,7 +525,6 @@ std::vector<pcl::Vertices> RTABMapApp::filterOrganizedPolygons(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int biggestCluster = 0;
|
|
||||||
unsigned int biggestClusterSize = 0;
|
unsigned int biggestClusterSize = 0;
|
||||||
for(std::map<int, std::list<int> >::iterator iter=clusters.begin(); iter!=clusters.end(); ++iter)
|
for(std::map<int, std::list<int> >::iterator iter=clusters.begin(); iter!=clusters.end(); ++iter)
|
||||||
{
|
{
|
||||||
@@ -533,12 +533,11 @@ std::vector<pcl::Vertices> RTABMapApp::filterOrganizedPolygons(
|
|||||||
if(iter->second.size() > biggestClusterSize)
|
if(iter->second.size() > biggestClusterSize)
|
||||||
{
|
{
|
||||||
biggestClusterSize = iter->second.size();
|
biggestClusterSize = iter->second.size();
|
||||||
biggestCluster = iter->first;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unsigned int minClusterSize = (unsigned int)(float(biggestClusterSize)*clusterRatio_);
|
unsigned int minClusterSize = (unsigned int)(float(biggestClusterSize)*clusterRatio_);
|
||||||
LOGI("Biggest cluster is %d = %d -> minClusterSize(ratio=%f)=%d",
|
LOGI("Biggest cluster %d -> minClusterSize(ratio=%f)=%d",
|
||||||
biggestCluster, biggestClusterSize, clusterRatio_, (int)minClusterSize);
|
biggestClusterSize, clusterRatio_, (int)minClusterSize);
|
||||||
|
|
||||||
std::vector<pcl::Vertices> filteredPolygons(polygons.size());
|
std::vector<pcl::Vertices> filteredPolygons(polygons.size());
|
||||||
int oi = 0;
|
int oi = 0;
|
||||||
@@ -1558,6 +1557,14 @@ void RTABMapApp::setRawScanSaved(bool enabled)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RTABMapApp::setCameraColor(bool enabled)
|
||||||
|
{
|
||||||
|
if(cameraColor_ != enabled)
|
||||||
|
{
|
||||||
|
cameraColor_ = enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RTABMapApp::setFullResolution(bool enabled)
|
void RTABMapApp::setFullResolution(bool enabled)
|
||||||
{
|
{
|
||||||
if(fullResolution_ != enabled)
|
if(fullResolution_ != enabled)
|
||||||
@@ -1858,6 +1865,12 @@ cv::Mat RTABMapApp::mergeTextures(pcl::TextureMesh & mesh, int textureSize) cons
|
|||||||
{
|
{
|
||||||
cv::multiply(resizedImage, createdMeshes_.at(textures[i]).gain, resizedImage);
|
cv::multiply(resizedImage, createdMeshes_.at(textures[i]).gain, resizedImage);
|
||||||
}
|
}
|
||||||
|
if(resizedImage.type() == CV_8UC1)
|
||||||
|
{
|
||||||
|
cv::Mat resizedImageColor;
|
||||||
|
cv::cvtColor(resizedImage,resizedImageColor,CV_GRAY2RGB);
|
||||||
|
resizedImage = resizedImageColor;
|
||||||
|
}
|
||||||
UASSERT(resizedImage.type() == globalTexture.type());
|
UASSERT(resizedImage.type() == globalTexture.type());
|
||||||
resizedImage.copyTo(globalTexture(cv::Rect(u, v, resizedImage.cols, resizedImage.rows)));
|
resizedImage.copyTo(globalTexture(cv::Rect(u, v, resizedImage.cols, resizedImage.rows)));
|
||||||
}
|
}
|
||||||
@@ -1979,7 +1992,9 @@ bool RTABMapApp::exportMesh(
|
|||||||
|
|
||||||
UTimer timer;
|
UTimer timer;
|
||||||
LOGI("Assemble clouds (%d)...", (int)poses.size());
|
LOGI("Assemble clouds (%d)...", (int)poses.size());
|
||||||
|
#ifndef DISABLE_LOG
|
||||||
int cloudCount=0;
|
int cloudCount=0;
|
||||||
|
#endif
|
||||||
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr mergedClouds(new pcl::PointCloud<pcl::PointXYZRGBNormal>);
|
pcl::PointCloud<pcl::PointXYZRGBNormal>::Ptr mergedClouds(new pcl::PointCloud<pcl::PointXYZRGBNormal>);
|
||||||
for(std::map<int, rtabmap::Transform>::iterator iter=poses.begin();
|
for(std::map<int, rtabmap::Transform>::iterator iter=poses.begin();
|
||||||
iter!= poses.end();
|
iter!= poses.end();
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ class RTABMapApp : public UEventsHandler {
|
|||||||
void setGridVisible(bool visible);
|
void setGridVisible(bool visible);
|
||||||
void setAutoExposure(bool enabled);
|
void setAutoExposure(bool enabled);
|
||||||
void setRawScanSaved(bool enabled);
|
void setRawScanSaved(bool enabled);
|
||||||
|
void setCameraColor(bool enabled);
|
||||||
void setFullResolution(bool enabled);
|
void setFullResolution(bool enabled);
|
||||||
void setSmoothing(bool enabled);
|
void setSmoothing(bool enabled);
|
||||||
void setAppendMode(bool enabled);
|
void setAppendMode(bool enabled);
|
||||||
@@ -189,6 +190,7 @@ class RTABMapApp : public UEventsHandler {
|
|||||||
bool autoExposure_;
|
bool autoExposure_;
|
||||||
bool rawScanSaved_;
|
bool rawScanSaved_;
|
||||||
bool smoothing_;
|
bool smoothing_;
|
||||||
|
bool cameraColor_;
|
||||||
bool fullResolution_;
|
bool fullResolution_;
|
||||||
bool appendMode_;
|
bool appendMode_;
|
||||||
float maxCloudDepth_;
|
float maxCloudDepth_;
|
||||||
|
|||||||
@@ -223,6 +223,12 @@ Java_com_introlab_rtabmap_RTABMapLib_setSmoothing(
|
|||||||
return app.setSmoothing(enabled);
|
return app.setSmoothing(enabled);
|
||||||
}
|
}
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
|
Java_com_introlab_rtabmap_RTABMapLib_setCameraColor(
|
||||||
|
JNIEnv*, jobject, bool enabled)
|
||||||
|
{
|
||||||
|
return app.setCameraColor(enabled);
|
||||||
|
}
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
Java_com_introlab_rtabmap_RTABMapLib_setAppendMode(
|
Java_com_introlab_rtabmap_RTABMapLib_setAppendMode(
|
||||||
JNIEnv*, jobject, bool enabled)
|
JNIEnv*, jobject, bool enabled)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -80,6 +80,11 @@
|
|||||||
android:title="@string/pref_title_smoothing"
|
android:title="@string/pref_title_smoothing"
|
||||||
android:summary="@string/pref_summary_smoothing"
|
android:summary="@string/pref_summary_smoothing"
|
||||||
android:defaultValue="@string/pref_default_smoothing"/>
|
android:defaultValue="@string/pref_default_smoothing"/>
|
||||||
|
<SwitchPreference
|
||||||
|
android:key="@string/pref_key_fisheye"
|
||||||
|
android:title="@string/pref_title_fisheye"
|
||||||
|
android:summary="@string/pref_summary_fisheye"
|
||||||
|
android:defaultValue="@string/pref_default_fisheye"/>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:title="@string/pref_title_mapping_core">
|
android:title="@string/pref_title_mapping_core">
|
||||||
|
|||||||
@@ -64,6 +64,8 @@
|
|||||||
<string name="pref_default_resolution">false</string>
|
<string name="pref_default_resolution">false</string>
|
||||||
<string name="pref_key_smoothing">pref_key_smoothing</string>
|
<string name="pref_key_smoothing">pref_key_smoothing</string>
|
||||||
<string name="pref_default_smoothing">true</string>
|
<string name="pref_default_smoothing">true</string>
|
||||||
|
<string name="pref_key_fisheye">pref_key_fisheye</string>
|
||||||
|
<string name="pref_default_fisheye">false</string>
|
||||||
|
|
||||||
<string name="pref_key_update_rate">pref_key_update_rate</string>
|
<string name="pref_key_update_rate">pref_key_update_rate</string>
|
||||||
<string name="pref_default_update_rate">1</string>
|
<string name="pref_default_update_rate">1</string>
|
||||||
@@ -240,9 +242,11 @@
|
|||||||
<string name="pref_title_auto_exposure">Auto Exposure</string>
|
<string name="pref_title_auto_exposure">Auto Exposure</string>
|
||||||
<string name="pref_summary_auto_exposure">Adjust camera exposure depending on the lighting to get always maximum contrast. This may change texture color between scanned images. Color correction option in Post-Processing can help to uniformize colors. May not work on some devices.</string>
|
<string name="pref_summary_auto_exposure">Adjust camera exposure depending on the lighting to get always maximum contrast. This may change texture color between scanned images. Color correction option in Post-Processing can help to uniformize colors. May not work on some devices.</string>
|
||||||
<string name="pref_title_resolution">HD Mode</string>
|
<string name="pref_title_resolution">HD Mode</string>
|
||||||
<string name="pref_summary_resolution">Save HD images if you want very detailed textures. More memory will be required.</string>
|
<string name="pref_summary_resolution">Save HD images of the color camera if you want very detailed textures. More memory will be required.</string>
|
||||||
<string name="pref_title_smoothing">Smoothing</string>
|
<string name="pref_title_smoothing">Smoothing</string>
|
||||||
<string name="pref_summary_smoothing">Smooth the point clouds.</string>
|
<string name="pref_summary_smoothing">Smooth the point clouds.</string>
|
||||||
|
<string name="pref_title_fisheye">Fish Eye Camera</string>
|
||||||
|
<string name="pref_summary_fisheye">Use fish eye camera instead of the color camera. Cannot be used on Yellowstone tablet.</string>
|
||||||
<string name="pref_title_update_rate">Update Rate</string>
|
<string name="pref_title_update_rate">Update Rate</string>
|
||||||
<string name="pref_summary_update_rate">Rate at which a new node is added to map.</string>
|
<string name="pref_summary_update_rate">Rate at which a new node is added to map.</string>
|
||||||
<string name="pref_title_time_thr">Time Limit</string>
|
<string name="pref_title_time_thr">Time Limit</string>
|
||||||
|
|||||||
@@ -460,6 +460,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
RTABMapLib.setRawScanSaved(sharedPref.getBoolean(getString(R.string.pref_key_raw_scan_saved), Boolean.parseBoolean(getString(R.string.pref_default_raw_scan_saved))));
|
RTABMapLib.setRawScanSaved(sharedPref.getBoolean(getString(R.string.pref_key_raw_scan_saved), Boolean.parseBoolean(getString(R.string.pref_default_raw_scan_saved))));
|
||||||
RTABMapLib.setFullResolution(sharedPref.getBoolean(getString(R.string.pref_key_resolution), Boolean.parseBoolean(getString(R.string.pref_default_resolution))));
|
RTABMapLib.setFullResolution(sharedPref.getBoolean(getString(R.string.pref_key_resolution), Boolean.parseBoolean(getString(R.string.pref_default_resolution))));
|
||||||
RTABMapLib.setSmoothing(sharedPref.getBoolean(getString(R.string.pref_key_smoothing), Boolean.parseBoolean(getString(R.string.pref_default_smoothing))));
|
RTABMapLib.setSmoothing(sharedPref.getBoolean(getString(R.string.pref_key_smoothing), Boolean.parseBoolean(getString(R.string.pref_default_smoothing))));
|
||||||
|
RTABMapLib.setCameraColor(!sharedPref.getBoolean(getString(R.string.pref_key_fisheye), Boolean.parseBoolean(getString(R.string.pref_default_fisheye))));
|
||||||
RTABMapLib.setAppendMode(sharedPref.getBoolean(getString(R.string.pref_key_append), Boolean.parseBoolean(getString(R.string.pref_default_append))));
|
RTABMapLib.setAppendMode(sharedPref.getBoolean(getString(R.string.pref_key_append), Boolean.parseBoolean(getString(R.string.pref_default_append))));
|
||||||
RTABMapLib.setMappingParameter("Rtabmap/DetectionRate", mUpdateRate);
|
RTABMapLib.setMappingParameter("Rtabmap/DetectionRate", mUpdateRate);
|
||||||
RTABMapLib.setMappingParameter("Rtabmap/TimeThr", mTimeThr);
|
RTABMapLib.setMappingParameter("Rtabmap/TimeThr", mTimeThr);
|
||||||
@@ -585,7 +586,9 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
|||||||
private void setAndroidOrientation() {
|
private void setAndroidOrientation() {
|
||||||
Display display = getWindowManager().getDefaultDisplay();
|
Display display = getWindowManager().getDefaultDisplay();
|
||||||
Camera.CameraInfo colorCameraInfo = new Camera.CameraInfo();
|
Camera.CameraInfo colorCameraInfo = new Camera.CameraInfo();
|
||||||
Camera.getCameraInfo(0, colorCameraInfo);
|
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
boolean fisheye = sharedPref.getBoolean(getString(R.string.pref_key_fisheye), Boolean.parseBoolean(getString(R.string.pref_default_fisheye)));
|
||||||
|
Camera.getCameraInfo(fisheye?1:0, colorCameraInfo);
|
||||||
RTABMapLib.setScreenRotation(display.getRotation(), colorCameraInfo.orientation);
|
RTABMapLib.setScreenRotation(display.getRotation(), colorCameraInfo.orientation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ public class RTABMapLib
|
|||||||
public static native void setRawScanSaved(boolean enabled);
|
public static native void setRawScanSaved(boolean enabled);
|
||||||
public static native void setFullResolution(boolean enabled);
|
public static native void setFullResolution(boolean enabled);
|
||||||
public static native void setSmoothing(boolean enabled);
|
public static native void setSmoothing(boolean enabled);
|
||||||
|
public static native void setCameraColor(boolean enabled);
|
||||||
public static native void setAppendMode(boolean enabled);
|
public static native void setAppendMode(boolean enabled);
|
||||||
public static native void setDataRecorderMode(boolean enabled);
|
public static native void setDataRecorderMode(boolean enabled);
|
||||||
public static native void setMaxCloudDepth(float value);
|
public static native void setMaxCloudDepth(float value);
|
||||||
|
|||||||
Reference in New Issue
Block a user