android: added occlusion detection using arcore depth api (for FPS view). Added depth from motion option in Mapping options.

This commit is contained in:
matlabbe
2020-06-29 20:25:58 -04:00
parent 2ee3445728
commit b7ada1992e
11 changed files with 167 additions and 51 deletions

View File

@@ -37,14 +37,16 @@ namespace rtabmap {
////////////////////////////// //////////////////////////////
// CameraARCore // CameraARCore
////////////////////////////// //////////////////////////////
CameraARCore::CameraARCore(void* env, void* context, void* activity, bool smoothing): CameraARCore::CameraARCore(void* env, void* context, void* activity, bool depthFromMotion, bool smoothing):
CameraMobile(smoothing), CameraMobile(smoothing),
env_(env), env_(env),
context_(context), context_(context),
activity_(activity), activity_(activity),
arInstallRequested_(false), arInstallRequested_(false),
textureId_(9999), textureId_(9999),
uvs_initialized_(false) uvs_initialized_(false),
updateOcclusionImage_(false),
depthFromMotion_(depthFromMotion)
{ {
} }
@@ -162,8 +164,8 @@ bool CameraARCore::init(const std::string & calibrationFolder, const std::string
UASSERT(ArSession_create(env_, context_, &arSession_) == AR_SUCCESS); UASSERT(ArSession_create(env_, context_, &arSession_) == AR_SUCCESS);
UASSERT(arSession_); UASSERT(arSession_);
int32_t is_depth_supported = 0; // Disabled by default, depth is not super accurate for mapping int32_t is_depth_supported = 0;
//ArSession_isDepthModeSupported(arSession_, AR_DEPTH_MODE_AUTOMATIC, &is_depth_supported); ArSession_isDepthModeSupported(arSession_, AR_DEPTH_MODE_AUTOMATIC, &is_depth_supported);
ArConfig_create(arSession_, &arConfig_); ArConfig_create(arSession_, &arConfig_);
UASSERT(arConfig_); UASSERT(arConfig_);
@@ -277,6 +279,7 @@ void CameraARCore::close()
arPose_ = nullptr; arPose_ = nullptr;
CameraMobile::close(); CameraMobile::close();
occlusionImage_ = cv::Mat();
} }
LaserScan CameraARCore::scanFromPointCloudData( LaserScan CameraARCore::scanFromPointCloudData(
@@ -429,8 +432,7 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
ArStatus status = ArFrame_acquireCameraImage(arSession_, arFrame_, &image); ArStatus status = ArFrame_acquireCameraImage(arSession_, arFrame_, &image);
if(status == AR_SUCCESS) if(status == AR_SUCCESS)
{ {
cv::Mat outputDepth; if(is_depth_supported && (updateOcclusionImage_||depthFromMotion_))
if(is_depth_supported)
{ {
LOGD("Acquire depth image!"); LOGD("Acquire depth image!");
ArImage * depthImage = nullptr; ArImage * depthImage = nullptr;
@@ -444,36 +446,24 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
int planeCount; int planeCount;
ArImage_getNumberOfPlanes(arSession_, depthImage, &planeCount); ArImage_getNumberOfPlanes(arSession_, depthImage, &planeCount);
LOGD("planeCount=%d", planeCount); LOGD("planeCount=%d", planeCount);
UASSERT_MSG(planeCount == 1, UASSERT_MSG(planeCount == 1, uFormat("Error: getNumberOfPlanes() planceCount = %d", planeCount).c_str());
uFormat("Error: getNumberOfPlanes() planceCount = %d", planeCount).c_str());
const uint8_t *data = nullptr; const uint8_t *data = nullptr;
int len = 0; int len = 0;
int stride; int stride;
int width; int depth_width;
int height; int depth_height;
ArImage_getWidth(arSession_, depthImage, &width); ArImage_getWidth(arSession_, depthImage, &depth_width);
ArImage_getHeight(arSession_, depthImage, &height); ArImage_getHeight(arSession_, depthImage, &depth_height);
ArImage_getPlaneRowStride(arSession_, depthImage, 0, &stride); ArImage_getPlaneRowStride(arSession_, depthImage, 0, &stride);
ArImage_getPlaneData(arSession_, depthImage, 0, &data, &len); ArImage_getPlaneData(arSession_, depthImage, 0, &data, &len);
LOGD("width=%d, height=%d, bytes=%d stride=%d", width, height, len, stride); LOGD("width=%d, height=%d, bytes=%d stride=%d", depth_width, depth_height, len, stride);
outputDepth = cv::Mat(height, width, CV_16UC1); occlusionImage_ = cv::Mat(depth_height, depth_width, CV_16UC1, (void*)data).clone();
uint16_t *dataShort = (uint16_t *)data;
uint16_t max=0x0; float scaleX = (float)depth_width / (float)width;
for (int y = 0; y < outputDepth.rows; ++y) float scaleY = (float)depth_height / (float)height;
{ occlusionModel_ = CameraModel(fx*scaleX, fy*scaleY, cx*scaleX, cy*scaleY, pose*deviceTColorCamera_, 0, cv::Size(depth_width, depth_height));
for (int x = 0; x < outputDepth.cols; ++x)
{
uint16_t depthSample = dataShort[y*outputDepth.cols + x];
uint16_t depthRange = (depthSample & 0x1FFF); // first 3 bits are confidence
outputDepth.at<uint16_t>(y,x) = depthRange;
if(depthRange > max)
{
max = depthRange;
}
}
}
} }
ArImage_release(depthImage); ArImage_release(depthImage);
} }
@@ -545,7 +535,7 @@ SensorData CameraARCore::captureImage(CameraInfo * info)
LOGI("pointCloud empty"); LOGI("pointCloud empty");
} }
data = SensorData(scan, rgb, outputDepth, model, 0, stamp); data = SensorData(scan, rgb, depthFromMotion_?occlusionImage_:cv::Mat(), model, 0, stamp);
data.setFeatures(kpts, kpts3, cv::Mat()); data.setFeatures(kpts, kpts3, cv::Mat());
} }
} }
@@ -619,11 +609,6 @@ void CameraARCore::capturePoseOnly()
uvs_initialized_ = true; uvs_initialized_ = true;
} }
/*ArImage* ar_image = nullptr;
ArStatus status =
ArFrame_acquireCameraImage(arSession_, arFrame_, &ar_image);
ArImage_release(ar_image);
*/
ArCamera* ar_camera; ArCamera* ar_camera;
ArFrame_acquireCamera(arSession_, arFrame_, &ar_camera); ArFrame_acquireCamera(arSession_, arFrame_, &ar_camera);
@@ -649,6 +634,52 @@ void CameraARCore::capturePoseOnly()
pose = rtabmap::rtabmap_world_T_opengl_world * pose * rtabmap::opengl_world_T_rtabmap_world; pose = rtabmap::rtabmap_world_T_opengl_world * pose * rtabmap::opengl_world_T_rtabmap_world;
this->poseReceived(pose); this->poseReceived(pose);
} }
int32_t is_depth_supported = 0;
ArSession_isDepthModeSupported(arSession_, AR_DEPTH_MODE_AUTOMATIC, &is_depth_supported);
if(is_depth_supported && updateOcclusionImage_)
{
LOGD("Acquire depth image!");
ArImage * depthImage = nullptr;
ArFrame_acquireDepthImage(arSession_, arFrame_, &depthImage);
ArImageFormat format;
ArImage_getFormat(arSession_, depthImage, &format);
if(format == AR_IMAGE_FORMAT_DEPTH16)
{
LOGD("Depth format detected!");
int planeCount;
ArImage_getNumberOfPlanes(arSession_, depthImage, &planeCount);
LOGD("planeCount=%d", planeCount);
UASSERT_MSG(planeCount == 1, uFormat("Error: getNumberOfPlanes() planceCount = %d", planeCount).c_str());
const uint8_t *data = nullptr;
int len = 0;
int stride;
int width;
int height;
ArImage_getWidth(arSession_, depthImage, &width);
ArImage_getHeight(arSession_, depthImage, &height);
ArImage_getPlaneRowStride(arSession_, depthImage, 0, &stride);
ArImage_getPlaneData(arSession_, depthImage, 0, &data, &len);
LOGD("width=%d, height=%d, bytes=%d stride=%d", width, height, len, stride);
occlusionImage_ = cv::Mat(height, width, CV_16UC1, (void*)data).clone();
float fx,fy, cx, cy;
int32_t rgb_width, rgb_height;
ArCamera_getImageIntrinsics(arSession_, ar_camera, arCameraIntrinsics_);
ArCameraIntrinsics_getFocalLength(arSession_, arCameraIntrinsics_, &fx, &fy);
ArCameraIntrinsics_getPrincipalPoint(arSession_, arCameraIntrinsics_, &cx, &cy);
ArCameraIntrinsics_getImageDimensions(arSession_, arCameraIntrinsics_, &rgb_width, &rgb_height);
float scaleX = (float)width / (float)rgb_width;
float scaleY = (float)height / (float)rgb_height;
occlusionModel_ = CameraModel(fx*scaleX, fy*scaleY, cx*scaleX, cy*scaleY, pose*deviceTColorCamera_, 0, cv::Size(width, height));
}
ArImage_release(depthImage);
}
} }
ArCamera_release(ar_camera); ArCamera_release(ar_camera);

View File

@@ -60,13 +60,16 @@ public:
std::vector<cv::Point3f> * kpts3D = 0); std::vector<cv::Point3f> * kpts3D = 0);
public: public:
CameraARCore(void* env, void* context, void* activity, bool smoothing = false); CameraARCore(void* env, void* context, void* activity, bool depthFromMotion = false, bool smoothing = false);
virtual ~CameraARCore(); virtual ~CameraARCore();
bool uvsInitialized() const {return uvs_initialized_;} bool uvsInitialized() const {return uvs_initialized_;}
const float* uvsTransformed() const {return transformed_uvs_;} const float* uvsTransformed() const {return transformed_uvs_;}
void getVPMatrices(glm::mat4 & view, glm::mat4 & projection) const {view=viewMatrix_; projection=projectionMatrix_;} void getVPMatrices(glm::mat4 & view, glm::mat4 & projection) const {view=viewMatrix_; projection=projectionMatrix_;}
void updateOcclusionImage(bool enabled) {updateOcclusionImage_ = enabled;}
const cv::Mat & getOcclusionImage(CameraModel * model=0) const {if(model)*model=occlusionModel_; return occlusionImage_; }
virtual void setScreenRotationAndSize(ScreenRotation colorCameraToDisplayRotation, int width, int height); virtual void setScreenRotationAndSize(ScreenRotation colorCameraToDisplayRotation, int width, int height);
virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = ""); virtual bool init(const std::string & calibrationFolder = ".", const std::string & cameraName = "");
@@ -101,6 +104,11 @@ private:
bool uvs_initialized_ = false; bool uvs_initialized_ = false;
glm::mat4 viewMatrix_; glm::mat4 viewMatrix_;
glm::mat4 projectionMatrix_; glm::mat4 projectionMatrix_;
bool updateOcclusionImage_;
cv::Mat occlusionImage_;
CameraModel occlusionModel_;
bool depthFromMotion_;
}; };
} /* namespace rtabmap */ } /* namespace rtabmap */

View File

@@ -690,7 +690,7 @@ bool RTABMapApp::startCamera(JNIEnv* env, jobject iBinder, jobject context, jobj
else if(cameraDriver_ == 1) else if(cameraDriver_ == 1)
{ {
#ifdef RTABMAP_ARCORE #ifdef RTABMAP_ARCORE
camera_ = new rtabmap::CameraARCore(env, context, activity, smoothing_); camera_ = new rtabmap::CameraARCore(env, context, activity, depthFromMotion_, smoothing_);
#else #else
UERROR("RTAB-Map is not built with ARCore support!"); UERROR("RTAB-Map is not built with ARCore support!");
#endif #endif
@@ -1113,15 +1113,24 @@ int RTABMapApp::Render()
const float* uvsTransformed = 0; const float* uvsTransformed = 0;
glm::mat4 arProjectionMatrix(0); glm::mat4 arProjectionMatrix(0);
glm::mat4 arViewMatrix(0); glm::mat4 arViewMatrix(0);
rtabmap::Mesh occlusionMesh;
if((cameraDriver_ == 1 || cameraDriver_ == 2) && camera_!=0) if((cameraDriver_ == 1 || cameraDriver_ == 2) && camera_!=0)
{ {
boost::mutex::scoped_lock lock(cameraMutex_); boost::mutex::scoped_lock lock(cameraMutex_);
if(camera_!=0) if(camera_!=0)
{ {
camera_->spinOnce(); #ifdef RTABMAP_ARCORE
if(cameraDriver_ == 1) if(cameraDriver_ == 1)
{ {
((rtabmap::CameraARCore*)camera_)->updateOcclusionImage(!visualizingMesh_ && main_scene_.GetCameraType() == tango_gl::GestureCamera::kFirstPerson);
}
#endif
camera_->spinOnce();
#ifdef RTABMAP_ARCORE #ifdef RTABMAP_ARCORE
if(cameraDriver_ == 1)
{
if(main_scene_.background_renderer_ == 0) if(main_scene_.background_renderer_ == 0)
{ {
main_scene_.background_renderer_ = new BackgroundRenderer(); main_scene_.background_renderer_ = new BackgroundRenderer();
@@ -1131,12 +1140,31 @@ int RTABMapApp::Render()
{ {
uvsTransformed = ((rtabmap::CameraARCore*)camera_)->uvsTransformed(); uvsTransformed = ((rtabmap::CameraARCore*)camera_)->uvsTransformed();
((rtabmap::CameraARCore*)camera_)->getVPMatrices(arViewMatrix, arProjectionMatrix); ((rtabmap::CameraARCore*)camera_)->getVPMatrices(arViewMatrix, arProjectionMatrix);
//main_scene_.background_renderer_->Draw(uvsTransformed); }
if(!visualizingMesh_ && main_scene_.GetCameraType() == tango_gl::GestureCamera::kFirstPerson)
{
rtabmap::CameraModel occlusionModel;
cv::Mat occlusionImage = ((rtabmap::CameraARCore*)camera_)->getOcclusionImage(&occlusionModel);
if(occlusionModel.isValidForProjection())
{
pcl::IndicesPtr indices(new std::vector<int>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = rtabmap::util3d::cloudFromDepth(occlusionImage, occlusionModel, 1, 0, 0, indices.get());
cloud = rtabmap::util3d::transformPointCloud(cloud, rtabmap::opengl_world_T_rtabmap_world*occlusionModel.localTransform());
occlusionMesh.cloud.reset(new pcl::PointCloud<pcl::PointXYZRGB>());
pcl::copyPointCloud(*cloud, *occlusionMesh.cloud);
occlusionMesh.indices = indices;
occlusionMesh.polygons = rtabmap::util3d::organizedFastMesh(cloud, 1.0*M_PI/180.0, false, meshTrianglePix_);
}
else
{
UERROR("invalid occlusionModel: %f %f %f %f %dx%d", occlusionModel.fx(), occlusionModel.fy(), occlusionModel.cx(), occlusionModel.cy(), occlusionModel.imageWidth(), occlusionModel.imageHeight());
}
}
} }
#endif #endif
} }
} }
}
// process only pose events in visualization mode // process only pose events in visualization mode
rtabmap::Transform pose; rtabmap::Transform pose;
@@ -1820,7 +1848,7 @@ int RTABMapApp::Render()
fpsTime.restart(); fpsTime.restart();
main_scene_.setFrustumVisible(camera_!=0); main_scene_.setFrustumVisible(camera_!=0);
lastDrawnCloudsCount_ = main_scene_.Render(uvsTransformed, arViewMatrix, arProjectionMatrix); lastDrawnCloudsCount_ = main_scene_.Render(uvsTransformed, arViewMatrix, arProjectionMatrix, occlusionMesh);
if(renderingTime_ < fpsTime.elapsed()) if(renderingTime_ < fpsTime.elapsed())
{ {
renderingTime_ = fpsTime.elapsed(); renderingTime_ = fpsTime.elapsed();
@@ -2106,6 +2134,14 @@ void RTABMapApp::setSmoothing(bool enabled)
} }
} }
void RTABMapApp::setDepthFromMotion(bool enabled)
{
if(depthFromMotion_ != enabled)
{
depthFromMotion_ = enabled;
}
}
void RTABMapApp::setAppendMode(bool enabled) void RTABMapApp::setAppendMode(bool enabled)
{ {
if(appendMode_ != enabled) if(appendMode_ != enabled)

View File

@@ -110,6 +110,7 @@ class RTABMapApp : public UEventsHandler {
void setCameraColor(bool enabled); void setCameraColor(bool enabled);
void setFullResolution(bool enabled); void setFullResolution(bool enabled);
void setSmoothing(bool enabled); void setSmoothing(bool enabled);
void setDepthFromMotion(bool enabled);
void setAppendMode(bool enabled); void setAppendMode(bool enabled);
void setDataRecorderMode(bool enabled); void setDataRecorderMode(bool enabled);
void setMaxCloudDepth(float value); void setMaxCloudDepth(float value);
@@ -183,6 +184,7 @@ class RTABMapApp : public UEventsHandler {
bool trajectoryMode_; bool trajectoryMode_;
bool rawScanSaved_; bool rawScanSaved_;
bool smoothing_; bool smoothing_;
bool depthFromMotion_;
bool cameraColor_; bool cameraColor_;
bool fullResolution_; bool fullResolution_;
bool appendMode_; bool appendMode_;

View File

@@ -512,6 +512,19 @@ Java_com_introlab_rtabmap_RTABMapLib_setSmoothing(
} }
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_setDepthFromMotion(
JNIEnv*, jclass, jlong native_application, bool enabled)
{
if(native_application)
{
return native(native_application)->setDepthFromMotion(enabled);
}
else
{
UERROR("native_application is null!");
}
}
JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_setCameraColor( Java_com_introlab_rtabmap_RTABMapLib_setCameraColor(
JNIEnv*, jclass, jlong native_application, bool enabled) JNIEnv*, jclass, jlong native_application, bool enabled)
{ {

View File

@@ -367,7 +367,7 @@ bool intersectFrustumAABB(
} }
//Should only be called in OpenGL thread! //Should only be called in OpenGL thread!
int Scene::Render(const float * uvsTransformed, glm::mat4 arViewMatrix, glm::mat4 arProjectionMatrix) { int Scene::Render(const float * uvsTransformed, glm::mat4 arViewMatrix, glm::mat4 arProjectionMatrix, const rtabmap::Mesh & occlusionMesh) {
UASSERT(gesture_camera_ != 0); UASSERT(gesture_camera_ != 0);
if(currentPose_ == 0) if(currentPose_ == 0)
@@ -458,7 +458,7 @@ int Scene::Render(const float * uvsTransformed, glm::mat4 arViewMatrix, glm::mat
UTimer timer; UTimer timer;
bool onlineBlending = blending_ && gesture_camera_->GetCameraType()!=tango_gl::GestureCamera::kTopOrtho && mapRendering_ && meshRendering_ && cloudsToDraw.size()>1; bool onlineBlending = (renderBackgroundCamera && occlusionMesh.cloud.get() && occlusionMesh.cloud->size()) || (blending_ && gesture_camera_->GetCameraType()!=tango_gl::GestureCamera::kTopOrtho && mapRendering_ && meshRendering_ && cloudsToDraw.size()>1);
if(onlineBlending && fboId_) if(onlineBlending && fboId_)
{ {
// set the rendering destination to FBO // set the rendering destination to FBO
@@ -468,12 +468,20 @@ int Scene::Render(const float * uvsTransformed, glm::mat4 arViewMatrix, glm::mat
glClearColor(1, 1, 1, 1); glClearColor(1, 1, 1, 1);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
if(renderBackgroundCamera)
{
PointCloudDrawable drawable(occlusionMesh);
drawable.Render(projectionMatrix, viewMatrix, true, pointSize_, false, false, 999.0f);
}
else
{
// Draw scene // Draw scene
for(std::vector<PointCloudDrawable*>::const_iterator iter=cloudsToDraw.begin(); iter!=cloudsToDraw.end(); ++iter) for(std::vector<PointCloudDrawable*>::const_iterator iter=cloudsToDraw.begin(); iter!=cloudsToDraw.end(); ++iter)
{ {
// set large distance to cam to use low res polygons for fast processing // set large distance to cam to use low res polygons for fast processing
(*iter)->Render(projectionMatrix, viewMatrix, meshRendering_, pointSize_, false, false, 999.0f); (*iter)->Render(projectionMatrix, viewMatrix, meshRendering_, pointSize_, false, false, 999.0f);
} }
}
// back to normal window-system-provided framebuffer // back to normal window-system-provided framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0); // unbind glBindFramebuffer(GL_FRAMEBUFFER, 0); // unbind
@@ -512,6 +520,10 @@ int Scene::Render(const float * uvsTransformed, glm::mat4 arViewMatrix, glm::mat
if(renderBackgroundCamera) if(renderBackgroundCamera)
{ {
background_renderer_->Draw(uvsTransformed); background_renderer_->Draw(uvsTransformed);
//To debug occlusion image:
//PointCloudDrawable drawable(occlusionMesh);
//drawable.Render(projectionMatrix, viewMatrix, true, pointSize_, false, false, 999.0f);
} }
if(!currentPose_->isNull()) if(!currentPose_->isNull())

View File

@@ -72,13 +72,14 @@ class Scene {
// frame's timestamp. // frame's timestamp.
// @param: point_cloud_vertices, point cloud's vertices of the current point // @param: point_cloud_vertices, point cloud's vertices of the current point
// frame. // frame.
int Render(const float * uvsTransformed = 0, glm::mat4 arViewMatrix = glm::mat4(0), glm::mat4 arProjectionMatrix=glm::mat4(0)); int Render(const float * uvsTransformed = 0, glm::mat4 arViewMatrix = glm::mat4(0), glm::mat4 arProjectionMatrix=glm::mat4(0), const rtabmap::Mesh & occlusionMesh=rtabmap::Mesh());
// Set render camera's viewing angle, first person, third person or top down. // Set render camera's viewing angle, first person, third person or top down.
// //
// @param: camera_type, camera type includes first person, third person and // @param: camera_type, camera type includes first person, third person and
// top down // top down
void SetCameraType(tango_gl::GestureCamera::CameraType camera_type); void SetCameraType(tango_gl::GestureCamera::CameraType camera_type);
tango_gl::GestureCamera::CameraType GetCameraType() const {return gesture_camera_->GetCameraType();}
void SetCameraPose(const rtabmap::Transform & pose); // opengl camera void SetCameraPose(const rtabmap::Transform & pose); // opengl camera
rtabmap::Transform GetCameraPose() const {return currentPose_!=0?*currentPose_:rtabmap::Transform();} rtabmap::Transform GetCameraPose() const {return currentPose_!=0?*currentPose_:rtabmap::Transform();}

View File

@@ -98,6 +98,11 @@
android:summary="@string/pref_summary_resolution" android:summary="@string/pref_summary_resolution"
android:defaultValue="@string/pref_default_resolution"/> android:defaultValue="@string/pref_default_resolution"/>
<com.introlab.rtabmap.CustomSwitchPreference <com.introlab.rtabmap.CustomSwitchPreference
android:key="@string/pref_key_depth_from_motion"
android:title="@string/pref_title_depth_from_motion"
android:summary="@string/pref_summary_depth_from_motion"
android:defaultValue="@string/pref_default_depth_from_motion"/>
<com.introlab.rtabmap.CustomSwitchPreference
android:key="@string/pref_key_smoothing" android:key="@string/pref_key_smoothing"
android:title="@string/pref_title_smoothing" android:title="@string/pref_title_smoothing"
android:summary="@string/pref_summary_smoothing" android:summary="@string/pref_summary_smoothing"

View File

@@ -81,6 +81,8 @@
<string name="pref_key_camera_driver">pref_key_camera_driver</string> <string name="pref_key_camera_driver">pref_key_camera_driver</string>
<string name="pref_default_camera_driver">0</string> <string name="pref_default_camera_driver">0</string>
<string name="pref_key_depth_from_motion">pref_key_depth_from_motion</string>
<string name="pref_default_depth_from_motion">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>
<string name="pref_key_max_speed">pref_key_max_speed</string> <string name="pref_key_max_speed">pref_key_max_speed</string>
@@ -323,6 +325,8 @@
<string name="pref_title_mapping_database">Database</string> <string name="pref_title_mapping_database">Database</string>
<string name="pref_title_camera_driver">Camera Driver</string> <string name="pref_title_camera_driver">Camera Driver</string>
<string name="pref_summary_camera_driver">AR sdk use for capturing 6DoF poses and images. A TOF camera is required to record a 3D model.</string> <string name="pref_summary_camera_driver">AR sdk use for capturing 6DoF poses and images. A TOF camera is required to record a 3D model.</string>
<string name="pref_title_depth_from_motion">Depth From Motion</string>
<string name="pref_summary_depth_from_motion">Use ARCore\'s depth API to compute depth image from motion. If the phone has a TOF camera and is supported by ARCore, results should be better. Currently supported only with ARCore NDK driver.</string>
<string name="pref_title_append">Append Mode</string> <string name="pref_title_append">Append Mode</string>
<string name="pref_summary_append">When resuming mapping, wait for a relocalization on the current map before starting a new map.</string> <string name="pref_summary_append">When resuming mapping, wait for a relocalization on the current map before starting a new map.</string>
<string name="pref_title_resolution">HD Mode</string> <string name="pref_title_resolution">HD Mode</string>

View File

@@ -992,6 +992,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
RTABMapLib.setRawScanSaved(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_raw_scan_saved), Boolean.parseBoolean(getString(R.string.pref_default_raw_scan_saved)))); RTABMapLib.setRawScanSaved(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_raw_scan_saved), Boolean.parseBoolean(getString(R.string.pref_default_raw_scan_saved))));
RTABMapLib.setFullResolution(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_resolution), Boolean.parseBoolean(getString(R.string.pref_default_resolution)))); RTABMapLib.setFullResolution(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_resolution), Boolean.parseBoolean(getString(R.string.pref_default_resolution))));
RTABMapLib.setSmoothing(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_smoothing), Boolean.parseBoolean(getString(R.string.pref_default_smoothing)))); RTABMapLib.setSmoothing(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_smoothing), Boolean.parseBoolean(getString(R.string.pref_default_smoothing))));
RTABMapLib.setDepthFromMotion(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_depth_from_motion), Boolean.parseBoolean(getString(R.string.pref_default_depth_from_motion))));
RTABMapLib.setCameraColor(nativeApplication, !sharedPref.getBoolean(getString(R.string.pref_key_fisheye), Boolean.parseBoolean(getString(R.string.pref_default_fisheye)))); RTABMapLib.setCameraColor(nativeApplication, !sharedPref.getBoolean(getString(R.string.pref_key_fisheye), Boolean.parseBoolean(getString(R.string.pref_default_fisheye))));
RTABMapLib.setAppendMode(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_append), Boolean.parseBoolean(getString(R.string.pref_default_append)))); RTABMapLib.setAppendMode(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_append), Boolean.parseBoolean(getString(R.string.pref_default_append))));
RTABMapLib.setMappingParameter(nativeApplication, "Rtabmap/DetectionRate", mUpdateRate); RTABMapLib.setMappingParameter(nativeApplication, "Rtabmap/DetectionRate", mUpdateRate);
@@ -1162,6 +1163,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
String cameraDriverStr = sharedPref.getString(getString(R.string.pref_key_camera_driver), getString(R.string.pref_default_camera_driver)); String cameraDriverStr = sharedPref.getString(getString(R.string.pref_key_camera_driver), getString(R.string.pref_default_camera_driver));
final boolean depthFromMotion = sharedPref.getBoolean(getString(R.string.pref_key_depth_from_motion), Boolean.parseBoolean(getString(R.string.pref_default_depth_from_motion)));
mCameraDriver = Integer.parseInt(cameraDriverStr); mCameraDriver = Integer.parseInt(cameraDriverStr);
if(!DISABLE_LOG) Log.i(TAG, String.format("startCamera() driver=%d", mCameraDriver)); if(!DISABLE_LOG) Log.i(TAG, String.format("startCamera() driver=%d", mCameraDriver));
@@ -1218,7 +1220,8 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
} }
Thread bindThread = new Thread(new Runnable() { Thread bindThread = new Thread(new Runnable() {
public void run() { public void run() {
if(mCameraDriver==1)
if(mCameraDriver==1 && !depthFromMotion)
{ {
RTABMapLib.setMeshRendering( RTABMapLib.setMeshRendering(
nativeApplication, nativeApplication,
@@ -1263,7 +1266,7 @@ public class RTABMapActivity extends FragmentActivity implements OnClickListener
} }
else else
{ {
if((mState==State.STATE_IDLE || mState==State.STATE_WELCOME) && mCameraDriver == 1) if((mState==State.STATE_IDLE || mState==State.STATE_WELCOME) && mCameraDriver == 1 && !depthFromMotion)
{ {
mToast.makeText(getApplicationContext(), "Currently ARCore NDK driver doesn't support depth, only poses, RGB images and 3d features can be recorded.", mToast.LENGTH_LONG).show(); mToast.makeText(getApplicationContext(), "Currently ARCore NDK driver doesn't support depth, only poses, RGB images and 3d features can be recorded.", mToast.LENGTH_LONG).show();
} }

View File

@@ -72,6 +72,7 @@ public class RTABMapLib
public static native void setRawScanSaved(long nativeApplication, boolean enabled); public static native void setRawScanSaved(long nativeApplication, boolean enabled);
public static native void setFullResolution(long nativeApplication, boolean enabled); public static native void setFullResolution(long nativeApplication, boolean enabled);
public static native void setSmoothing(long nativeApplication, boolean enabled); public static native void setSmoothing(long nativeApplication, boolean enabled);
public static native void setDepthFromMotion(long nativeApplication, boolean enabled);
public static native void setCameraColor(long nativeApplication, boolean enabled); public static native void setCameraColor(long nativeApplication, boolean enabled);
public static native void setAppendMode(long nativeApplication, boolean enabled); public static native void setAppendMode(long nativeApplication, boolean enabled);
public static native void setDataRecorderMode(long nativeApplication, boolean enabled); public static native void setDataRecorderMode(long nativeApplication, boolean enabled);