mirror of
https://github.com/introlab/rtabmap_ros.git
synced 2026-10-08 02:37:45 +08:00
Tango: 0.12.0 (performance optimization, time and memory)
This commit is contained in:
@@ -36,6 +36,10 @@ import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Typeface;
|
||||
import android.hardware.Camera;
|
||||
import android.graphics.Point;
|
||||
import android.hardware.display.DisplayManager;
|
||||
@@ -52,6 +56,7 @@ import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.TextPaint;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.view.Menu;
|
||||
@@ -93,6 +98,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
public static final String RTABMAP_TMP_DB = "rtabmap.tmp.db";
|
||||
public static final String RTABMAP_TMP_DIR = "tmp/";
|
||||
public static final String RTABMAP_TMP_FILENAME = "map";
|
||||
public static final String RTABMAP_SDCARD_PATH = "/sdcard/";
|
||||
|
||||
public static final String RTABMAP_AUTH_TOKEN_KEY = "com.introlab.rtabmap.AUTH_TOKEN";
|
||||
public static final String RTABMAP_FILENAME_KEY = "com.introlab.rtabmap.FILENAME";
|
||||
@@ -136,6 +142,8 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
private MenuItem mItemRenderingMesh;
|
||||
private MenuItem mItemRenderingTextureMesh;
|
||||
private MenuItem mItemDataRecorderMode;
|
||||
private MenuItem mItemStatusVisibility;
|
||||
private MenuItem mItemDebugVisibility;
|
||||
|
||||
private ToggleButton mButtonFirst;
|
||||
private ToggleButton mButtonThird;
|
||||
@@ -149,6 +157,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
|
||||
private String mOpenedDatabasePath = "";
|
||||
private String mWorkingDirectory = "";
|
||||
private String mWorkingDirectoryHuman = "";
|
||||
|
||||
private String mUpdateRate;
|
||||
private String mTimeThr;
|
||||
@@ -157,15 +166,16 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
private String mMinInliers;
|
||||
private String mMaxOptimizationError;
|
||||
|
||||
private LinearLayout mLayoutDebug;
|
||||
|
||||
private int mTotalLoopClosures = 0;
|
||||
private boolean mMapIsEmpty = false;
|
||||
private boolean mExportedOBJ = false;
|
||||
|
||||
private Toast mToast = null;
|
||||
|
||||
private AlertDialog mMemoryWarningDialog = null;
|
||||
|
||||
private Thread mMemStatusUpdateThread = null;
|
||||
private String[] mStatusTexts = new String[16];
|
||||
|
||||
//Tango Service connection.
|
||||
ServiceConnection mTangoServiceConnection = new ServiceConnection() {
|
||||
@@ -254,12 +264,10 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
mRenderer = new Renderer(this);
|
||||
mGLView.setRenderer(mRenderer);
|
||||
|
||||
mLayoutDebug = (LinearLayout) findViewById(R.id.debug_layout);
|
||||
mLayoutDebug.setVisibility(LinearLayout.GONE);
|
||||
|
||||
mProgressDialog = new ProgressDialog(this);
|
||||
mProgressDialog.setCanceledOnTouchOutside(false);
|
||||
mRenderer.setProgressDialog(mProgressDialog);
|
||||
mRenderer.setToast(mToast);
|
||||
|
||||
// Check if the Tango Core is out dated.
|
||||
if (!CheckTangoCoreVersion(MIN_TANGO_CORE_VERSION)) {
|
||||
@@ -270,6 +278,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
|
||||
mOpenedDatabasePath = "";
|
||||
mWorkingDirectory = "";
|
||||
mWorkingDirectoryHuman = "";
|
||||
mTotalLoopClosures = 0;
|
||||
|
||||
if(Environment.getExternalStorageState().compareTo(Environment.MEDIA_MOUNTED)==0)
|
||||
@@ -278,6 +287,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
mWorkingDirectory = extStore.getAbsolutePath() + "/" + getString(R.string.app_name) + "/";
|
||||
extStore = new File(mWorkingDirectory);
|
||||
extStore.mkdirs();
|
||||
mWorkingDirectoryHuman = RTABMAP_SDCARD_PATH + getString(R.string.app_name) + "/";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -407,6 +417,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
RTABMapLib.setAutoExposure(sharedPref.getBoolean(getString(R.string.pref_key_auto_exposure), Boolean.parseBoolean(getString(R.string.pref_default_auto_exposure))));
|
||||
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.setSmoothing(sharedPref.getBoolean(getString(R.string.pref_key_smoothing), Boolean.parseBoolean(getString(R.string.pref_default_smoothing))));
|
||||
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/TimeThr", mTimeThr);
|
||||
@@ -480,6 +491,12 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
|
||||
private void setCamera(int type)
|
||||
{
|
||||
// for convenience, for a refresh of the memory used
|
||||
stopUpdateStatusThread();
|
||||
mStatusTexts[1] = getString(R.string.memory)+String.valueOf(Debug.getNativeHeapAllocatedSize()/(1024*1024));
|
||||
mStatusTexts[2] = getString(R.string.free_memory)+String.valueOf(getFreeMemory());
|
||||
updateStatusTexts();
|
||||
|
||||
RTABMapLib.setCamera(type);
|
||||
mButtonFirst.setChecked(type==0);
|
||||
mButtonThird.setChecked(type==1);
|
||||
@@ -584,6 +601,8 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
mItemRenderingMesh = menu.findItem(R.id.mesh);
|
||||
mItemRenderingTextureMesh = menu.findItem(R.id.texture_mesh);
|
||||
mItemDataRecorderMode = menu.findItem(R.id.data_recorder);
|
||||
mItemStatusVisibility = menu.findItem(R.id.status);
|
||||
mItemDebugVisibility = menu.findItem(R.id.debug);
|
||||
mItemSave.setEnabled(false);
|
||||
mItemExport.setEnabled(false);
|
||||
mItemOpen.setEnabled(false);
|
||||
@@ -633,58 +652,107 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
activityManager.getMemoryInfo(mi);
|
||||
return mi.availMem / 0x100000L; // MB
|
||||
}
|
||||
|
||||
private void updateStatsUI(
|
||||
int nodes,
|
||||
int words,
|
||||
int points,
|
||||
int polygons,
|
||||
float updateTime,
|
||||
int loopClosureId,
|
||||
int highestHypId,
|
||||
int databaseMemoryUsed,
|
||||
int inliers,
|
||||
int matches,
|
||||
int featuresExtracted,
|
||||
float hypothesis,
|
||||
int nodesDrawn,
|
||||
float fps,
|
||||
int rejected,
|
||||
float rehearsalValue,
|
||||
float optimizationMaxError)
|
||||
|
||||
private void updateStatusTexts()
|
||||
{
|
||||
if(mButtonPause!=null)
|
||||
if(mItemStatusVisibility != null && mItemDebugVisibility != null)
|
||||
{
|
||||
if(mButtonPause.isChecked())
|
||||
if(mItemStatusVisibility.isChecked() && mItemDebugVisibility.isChecked())
|
||||
{
|
||||
((TextView)findViewById(R.id.status)).setText("Paused");
|
||||
mRenderer.updateTexts(mStatusTexts);
|
||||
}
|
||||
else if(mItemStatusVisibility.isChecked())
|
||||
{
|
||||
mRenderer.updateTexts(Arrays.copyOfRange(mStatusTexts, 0, 3));
|
||||
}
|
||||
else if(mItemDebugVisibility.isChecked())
|
||||
{
|
||||
mRenderer.updateTexts(Arrays.copyOfRange(mStatusTexts, 4, mStatusTexts.length));
|
||||
}
|
||||
else
|
||||
{
|
||||
String updateValue = mUpdateRate.compareTo("0")==0?"Max":mUpdateRate;
|
||||
((TextView)findViewById(R.id.status)).setText(mItemLocalizationMode.isChecked()?String.format("Localization (%s Hz)", updateValue):mItemDataRecorderMode.isChecked()?String.format("Recording (%s Hz)", updateValue):String.format("Mapping (%s Hz)", updateValue));
|
||||
mRenderer.updateTexts(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStatsUI(
|
||||
int processMemoryUsed,
|
||||
int loopClosureId,
|
||||
int inliers,
|
||||
int matches,
|
||||
int rejected,
|
||||
float optimizationMaxError,
|
||||
String[] statusTexts)
|
||||
{
|
||||
mStatusTexts = statusTexts;
|
||||
updateStatusTexts();
|
||||
|
||||
if(mButtonPause!=null)
|
||||
{
|
||||
if(!mButtonPause.isChecked())
|
||||
{
|
||||
//check if we are low in memory
|
||||
long memoryUsed = processMemoryUsed;
|
||||
long memoryFree = getFreeMemory();
|
||||
|
||||
if(memoryFree < 100)
|
||||
{
|
||||
mButtonPause.setChecked(true);
|
||||
pauseMapping();
|
||||
|
||||
if(mMemoryWarningDialog!=null)
|
||||
{
|
||||
mMemoryWarningDialog.dismiss();
|
||||
mMemoryWarningDialog = null;
|
||||
}
|
||||
|
||||
mMemoryWarningDialog = new AlertDialog.Builder(getActivity())
|
||||
.setTitle("Memory is full!")
|
||||
.setCancelable(false)
|
||||
.setMessage(String.format("Scanning has been paused because free memory is too "
|
||||
+ "low (%d MB). You should be able to save the database but some post-processing and exporting options may fail. "
|
||||
+ "\n\nNote that for large environments, you can save multiple databases and "
|
||||
+ "merge them with RTAB-Map Desktop version.", memoryUsed))
|
||||
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
mMemoryWarningDialog = null;
|
||||
}
|
||||
})
|
||||
.create();
|
||||
mMemoryWarningDialog.show();
|
||||
}
|
||||
else if(mMemoryWarningDialog == null && memoryUsed*3 > memoryFree && (mItemDataRecorderMode == null || !mItemDataRecorderMode.isChecked()))
|
||||
{
|
||||
mMemoryWarningDialog = new AlertDialog.Builder(getActivity())
|
||||
.setTitle("Warning: Memory is almost full!")
|
||||
.setCancelable(false)
|
||||
.setMessage(String.format("Free memory (%d MB) should be at least 3 times the "
|
||||
+ "memory used (%d MB) so that some post-processing and exporting options "
|
||||
+ "have enough memory to work correctly. If you just want to save the database "
|
||||
+ "after scanning, you can continue until the next warning.\n\n"
|
||||
+ "Note that showing only point clouds reduces memory needed for rendering.", memoryFree, memoryUsed))
|
||||
.setPositiveButton("Pause", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
mButtonPause.setChecked(true);
|
||||
pauseMapping();
|
||||
}
|
||||
})
|
||||
.setNeutralButton("Continue", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
}
|
||||
})
|
||||
.create();
|
||||
mMemoryWarningDialog.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
((TextView)findViewById(R.id.memory)).setText(String.valueOf(Debug.getNativeHeapAllocatedSize()/(1024*1024)));
|
||||
((TextView)findViewById(R.id.free_memory)).setText(String.valueOf(getFreeMemory()));
|
||||
((TextView)findViewById(R.id.points)).setText(String.valueOf(points));
|
||||
((TextView)findViewById(R.id.polygons)).setText(String.valueOf(polygons));
|
||||
((TextView)findViewById(R.id.nodes)).setText(String.format("%d (%d shown)", nodes, nodesDrawn));
|
||||
((TextView)findViewById(R.id.words)).setText(String.valueOf(words));
|
||||
((TextView)findViewById(R.id.database_size)).setText(String.valueOf(databaseMemoryUsed));
|
||||
((TextView)findViewById(R.id.inliers)).setText(String.valueOf(inliers));
|
||||
((TextView)findViewById(R.id.features)).setText(String.format("%d / %s", featuresExtracted, mMaxFeatures.compareTo("0")==0?"No Limit":mMaxFeatures.compareTo("-1")==0?"Disabled":mMaxFeatures));
|
||||
((TextView)findViewById(R.id.rehearsal)).setText(String.format("%.3f", rehearsalValue));
|
||||
((TextView)findViewById(R.id.update_time)).setText(String.format("%.3f / %s", updateTime, mTimeThr.compareTo("0")==0?"No Limit":mTimeThr));
|
||||
((TextView)findViewById(R.id.hypothesis)).setText(String.format("%.3f / %s (%d)", hypothesis, mLoopThr, loopClosureId>0?loopClosureId:highestHypId));
|
||||
((TextView)findViewById(R.id.fps)).setText(String.format("%.3f Hz", fps));
|
||||
|
||||
if(mButtonPause!=null && !mButtonPause.isChecked())
|
||||
{
|
||||
if(loopClosureId > 0)
|
||||
{
|
||||
++mTotalLoopClosures;
|
||||
|
||||
mToast.setText(String.format("Loop closure detected! (%d/%d inliers)", inliers, matches));
|
||||
mToast.show();
|
||||
}
|
||||
@@ -701,7 +769,6 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
mToast.show();
|
||||
}
|
||||
}
|
||||
((TextView)findViewById(R.id.total_loop)).setText(String.valueOf(mTotalLoopClosures));
|
||||
}
|
||||
|
||||
// called from jni
|
||||
@@ -713,10 +780,11 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
final float updateTime,
|
||||
final int loopClosureId,
|
||||
final int highestHypId,
|
||||
final int processMemoryUsed,
|
||||
final int databaseMemoryUsed,
|
||||
final int inliers,
|
||||
final int matches,
|
||||
final int features,
|
||||
final int featuresExtracted,
|
||||
final float hypothesis,
|
||||
final int nodesDrawn,
|
||||
final float fps,
|
||||
@@ -726,10 +794,57 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
{
|
||||
Log.i(TAG, String.format("updateStatsCallback()"));
|
||||
|
||||
final String[] statusTexts = new String[16];
|
||||
if(mButtonPause!=null)
|
||||
{
|
||||
if(mButtonPause.isChecked())
|
||||
{
|
||||
statusTexts[0] = getString(R.string.status)+"Paused";
|
||||
}
|
||||
else
|
||||
{
|
||||
String updateValue = mUpdateRate.compareTo("0")==0?"Max":mUpdateRate;
|
||||
statusTexts[0] = getString(R.string.status)+(mItemLocalizationMode.isChecked()?String.format("Localization (%s Hz)", updateValue):mItemDataRecorderMode.isChecked()?String.format("Recording (%s Hz)", updateValue):String.format("Mapping (%s Hz)", updateValue));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
statusTexts[0] = getString(R.string.status);
|
||||
}
|
||||
|
||||
stopUpdateStatusThread();
|
||||
|
||||
// getNativeHeapAllocatedSize() is too slow, so we need to use the estimate.
|
||||
// Multiply by 3/2 to match getNativeHeapAllocatedSize()
|
||||
final int adjustedMemoryUsed = (processMemoryUsed*3)/2;
|
||||
|
||||
statusTexts[1] = getString(R.string.memory)+adjustedMemoryUsed;
|
||||
statusTexts[2] = getString(R.string.free_memory)+getFreeMemory();
|
||||
|
||||
|
||||
if(loopClosureId > 0)
|
||||
{
|
||||
++mTotalLoopClosures;
|
||||
}
|
||||
|
||||
int index = 4;
|
||||
statusTexts[index++] = getString(R.string.nodes)+nodes+" (" + nodesDrawn + " shown)";
|
||||
statusTexts[index++] = getString(R.string.words)+words;
|
||||
statusTexts[index++] = getString(R.string.database_size)+databaseMemoryUsed;
|
||||
statusTexts[index++] = getString(R.string.points)+points;
|
||||
statusTexts[index++] = getString(R.string.polygons)+polygons;
|
||||
statusTexts[index++] = getString(R.string.update_time)+(int)(updateTime) + " / " + (mTimeThr.compareTo("0")==0?"No Limit":mTimeThr);
|
||||
statusTexts[index++] = getString(R.string.features)+featuresExtracted +" / " + (mMaxFeatures.compareTo("0")==0?"No Limit":mMaxFeatures.compareTo("-1")==0?"Disabled":mMaxFeatures);
|
||||
statusTexts[index++] = getString(R.string.rehearsal)+(int)(rehearsalValue*100.0f);
|
||||
statusTexts[index++] = getString(R.string.total_loop)+mTotalLoopClosures;
|
||||
statusTexts[index++] = getString(R.string.inliers)+inliers;
|
||||
statusTexts[index++] = getString(R.string.hypothesis)+(int)(hypothesis*100.0f) +" / " + (int)(Float.parseFloat(mLoopThr)*100.0f) + " (" + (loopClosureId>0?loopClosureId:highestHypId)+")";
|
||||
statusTexts[index++] = getString(R.string.fps)+(int)fps+" Hz";
|
||||
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
updateStatsUI(nodes, words, points, polygons, updateTime, loopClosureId, highestHypId, databaseMemoryUsed, inliers, matches, features, hypothesis, nodesDrawn, fps, rejected, rehearsalValue, optimizationMaxError);
|
||||
}
|
||||
public void run() {
|
||||
updateStatsUI(adjustedMemoryUsed, loopClosureId, inliers, matches, rejected, optimizationMaxError, statusTexts);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -743,14 +858,16 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
{
|
||||
if(mButtonPause.isChecked())
|
||||
{
|
||||
((TextView)findViewById(R.id.status)).setText(
|
||||
status == 1 && msg.isEmpty()?"Paused":msg);
|
||||
mStatusTexts[0] = getString(R.string.status)+(status == 1 && msg.isEmpty()?"Paused":msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
((TextView)findViewById(R.id.status)).setText(
|
||||
status == 1 && msg.isEmpty()?(mItemLocalizationMode!=null&&mItemLocalizationMode.isChecked()?"Localization":mItemDataRecorderMode!=null&&mItemDataRecorderMode.isChecked()?"Recording":"Mapping"):msg);
|
||||
mStatusTexts[0] = getString(R.string.status)+(status == 1 && msg.isEmpty()?(mItemLocalizationMode!=null&&mItemLocalizationMode.isChecked()?"Localization":mItemDataRecorderMode!=null&&mItemDataRecorderMode.isChecked()?"Recording":"Mapping"):msg);
|
||||
}
|
||||
|
||||
mStatusTexts[1] = getString(R.string.memory)+String.valueOf(Debug.getNativeHeapAllocatedSize()/(1024*1024));
|
||||
mStatusTexts[2] = getString(R.string.free_memory)+String.valueOf(getFreeMemory());
|
||||
updateStatusTexts();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -901,6 +1018,47 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
});
|
||||
workingThread.start();
|
||||
}
|
||||
|
||||
public void startUpdateStatusThread()
|
||||
{
|
||||
if(mMemStatusUpdateThread == null)
|
||||
{
|
||||
mMemStatusUpdateThread = new Thread() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!isInterrupted()) {
|
||||
Thread.sleep(1000);
|
||||
if(mState != RTABMapActivity.State.STATE_VISUALIZING)
|
||||
{
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mStatusTexts[1] = getString(R.string.memory)+String.valueOf(Debug.getNativeHeapAllocatedSize()/(1024*1024));
|
||||
mStatusTexts[2] = getString(R.string.free_memory)+String.valueOf(getFreeMemory());
|
||||
updateStatusTexts();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
};
|
||||
mMemStatusUpdateThread.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void stopUpdateStatusThread()
|
||||
{
|
||||
if(mMemStatusUpdateThread != null)
|
||||
{
|
||||
Thread tmp = mMemStatusUpdateThread;
|
||||
mMemStatusUpdateThread = null;
|
||||
tmp.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateState(State state)
|
||||
{
|
||||
@@ -920,32 +1078,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
mItemReset.setEnabled(false);
|
||||
mItemModes.setEnabled(false);
|
||||
mButtonPause.setVisibility(View.INVISIBLE);
|
||||
if(mMemStatusUpdateThread == null)
|
||||
{
|
||||
mMemStatusUpdateThread = new Thread() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!isInterrupted()) {
|
||||
Thread.sleep(1000);
|
||||
if(mState == RTABMapActivity.State.STATE_PROCESSING)
|
||||
{
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
((TextView)findViewById(R.id.memory)).setText(String.valueOf(Debug.getNativeHeapAllocatedSize()/(1024*1024)));
|
||||
((TextView)findViewById(R.id.free_memory)).setText(String.valueOf(getFreeMemory()));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
};
|
||||
mMemStatusUpdateThread.start();
|
||||
}
|
||||
startUpdateStatusThread();
|
||||
break;
|
||||
case STATE_VISUALIZING:
|
||||
mButtonLighting.setVisibility(View.VISIBLE);
|
||||
@@ -961,12 +1094,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
mItemModes.setEnabled(true);
|
||||
mButtonPause.setVisibility(View.INVISIBLE);
|
||||
mItemDataRecorderMode.setEnabled(mButtonPause.isChecked());
|
||||
if(mMemStatusUpdateThread != null)
|
||||
{
|
||||
Thread tmp = mMemStatusUpdateThread;
|
||||
mMemStatusUpdateThread = null;
|
||||
tmp.interrupt();
|
||||
}
|
||||
stopUpdateStatusThread();
|
||||
break;
|
||||
default:
|
||||
mButtonLighting.setVisibility(View.INVISIBLE);
|
||||
@@ -983,12 +1111,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
mButtonPause.setVisibility(View.VISIBLE);
|
||||
mItemDataRecorderMode.setEnabled(mButtonPause.isChecked());
|
||||
RTABMapLib.postExportation(false);
|
||||
if(mMemStatusUpdateThread != null)
|
||||
{
|
||||
Thread tmp = mMemStatusUpdateThread;
|
||||
mMemStatusUpdateThread = null;
|
||||
tmp.interrupt();
|
||||
}
|
||||
stopUpdateStatusThread();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1000,11 +1123,17 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
if(mButtonPause.isChecked())
|
||||
{
|
||||
RTABMapLib.setPausedMapping(true);
|
||||
((TextView)findViewById(R.id.status)).setText("Paused");
|
||||
|
||||
mStatusTexts[0] = getString(R.string.status)+"Paused";
|
||||
mStatusTexts[1] = getString(R.string.memory)+String.valueOf(Debug.getNativeHeapAllocatedSize()/(1024*1024));
|
||||
mStatusTexts[2] = getString(R.string.free_memory)+String.valueOf(getFreeMemory());
|
||||
updateStatusTexts();
|
||||
|
||||
mMapIsEmpty = false;
|
||||
mDateOnPause = new Date();
|
||||
|
||||
if(!mOnPause && !mItemLocalizationMode.isChecked() && !mItemDataRecorderMode.isChecked())
|
||||
long memoryFree = getFreeMemory();
|
||||
if(!mOnPause && !mItemLocalizationMode.isChecked() && !mItemDataRecorderMode.isChecked() && memoryFree >= 100)
|
||||
{
|
||||
// Do standard post processing?
|
||||
new AlertDialog.Builder(getActivity())
|
||||
@@ -1025,8 +1154,13 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mMemoryWarningDialog != null)
|
||||
{
|
||||
mMemoryWarningDialog.dismiss();
|
||||
mMemoryWarningDialog=null;
|
||||
}
|
||||
RTABMapLib.setPausedMapping(false);
|
||||
((TextView)findViewById(R.id.status)).setText(mItemLocalizationMode.isChecked()?"Localization":mItemDataRecorderMode.isChecked()?"Recording":"Mapping");
|
||||
|
||||
if(mItemDataRecorderMode.isChecked())
|
||||
{
|
||||
mToast.makeText(getActivity(), String.format("Data Recorder Mode: no map is created, only raw data is recorded."), mToast.LENGTH_LONG).show();
|
||||
@@ -1154,17 +1288,15 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
});
|
||||
workingThread.start();
|
||||
}
|
||||
else if(itemId == R.id.status)
|
||||
{
|
||||
item.setChecked(!item.isChecked());
|
||||
updateStatusTexts();
|
||||
}
|
||||
else if(itemId == R.id.debug)
|
||||
{
|
||||
item.setChecked(!item.isChecked());
|
||||
if(!item.isChecked())
|
||||
{
|
||||
mLayoutDebug.setVisibility(LinearLayout.GONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
mLayoutDebug.setVisibility(LinearLayout.VISIBLE);
|
||||
}
|
||||
updateStatusTexts();
|
||||
}
|
||||
else if(itemId == R.id.mesh || itemId == R.id.texture_mesh || itemId == R.id.point_cloud)
|
||||
{
|
||||
@@ -1256,62 +1388,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
.setMessage("Do you want to overwrite the existing file?")
|
||||
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
|
||||
final String newDatabasePath = mWorkingDirectory + fileName + ".db";
|
||||
mProgressDialog.setTitle("Saving");
|
||||
if(mOpenedDatabasePath.equals(newDatabasePath))
|
||||
{
|
||||
mProgressDialog.setMessage(String.format("Please wait while updating \"%s\"...", newDatabasePath));
|
||||
}
|
||||
else
|
||||
{
|
||||
mProgressDialog.setMessage(String.format("Please wait while saving \"%s\"...", newDatabasePath));
|
||||
}
|
||||
mProgressDialog.show();
|
||||
updateState(State.STATE_PROCESSING);
|
||||
Thread saveThread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
RTABMapLib.save(newDatabasePath); // save
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
if(mOpenedDatabasePath.equals(newDatabasePath))
|
||||
{
|
||||
mToast.makeText(getActivity(), String.format("Database \"%s\" updated.", newDatabasePath), mToast.LENGTH_LONG).show();
|
||||
}
|
||||
else
|
||||
{
|
||||
mToast.makeText(getActivity(), String.format("Database saved to \"%s\".", newDatabasePath), mToast.LENGTH_LONG).show();
|
||||
|
||||
Intent intent = new Intent(getActivity(), RTABMapActivity.class);
|
||||
// use System.currentTimeMillis() to have a unique ID for the pending intent
|
||||
PendingIntent pIntent = PendingIntent.getActivity(getActivity(), (int) System.currentTimeMillis(), intent, 0);
|
||||
|
||||
// build notification
|
||||
// the addAction re-use the same intent to keep the example short
|
||||
Notification n = new Notification.Builder(getActivity())
|
||||
.setContentTitle(getString(R.string.app_name))
|
||||
.setContentText(newDatabasePath + " saved!")
|
||||
.setSmallIcon(R.drawable.ic_launcher)
|
||||
.setContentIntent(pIntent)
|
||||
.setAutoCancel(true).build();
|
||||
|
||||
|
||||
NotificationManager notificationManager =
|
||||
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
|
||||
notificationManager.notify(0, n);
|
||||
}
|
||||
if(!mItemDataRecorderMode.isChecked())
|
||||
{
|
||||
mOpenedDatabasePath = newDatabasePath;
|
||||
}
|
||||
mProgressDialog.dismiss();
|
||||
updateState(State.STATE_IDLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
saveThread.start();
|
||||
saveDatabase(fileName);
|
||||
}
|
||||
})
|
||||
.setNegativeButton("No", new DialogInterface.OnClickListener() {
|
||||
@@ -1323,61 +1400,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
}
|
||||
else
|
||||
{
|
||||
final String newDatabasePath = mWorkingDirectory + fileName + ".db";
|
||||
mProgressDialog.setTitle("Saving");
|
||||
if(mOpenedDatabasePath.equals(newDatabasePath))
|
||||
{
|
||||
mProgressDialog.setMessage(String.format("Please wait while updating \"%s\"...", mOpenedDatabasePath));
|
||||
}
|
||||
else
|
||||
{
|
||||
mProgressDialog.setMessage(String.format("Please wait while saving \"%s\"...", newDatabasePath));
|
||||
}
|
||||
mProgressDialog.show();
|
||||
updateState(State.STATE_PROCESSING);
|
||||
Thread saveThread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
RTABMapLib.save(newDatabasePath); // save
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
if(mOpenedDatabasePath.equals(newDatabasePath))
|
||||
{
|
||||
mToast.makeText(getActivity(), String.format("Database \"%s\" updated.", newDatabasePath), mToast.LENGTH_LONG).show();
|
||||
}
|
||||
else
|
||||
{
|
||||
mToast.makeText(getActivity(), String.format("Database saved to \"%s\".", newDatabasePath), mToast.LENGTH_LONG).show();
|
||||
|
||||
Intent intent = new Intent(getActivity(), RTABMapActivity.class);
|
||||
// use System.currentTimeMillis() to have a unique ID for the pending intent
|
||||
PendingIntent pIntent = PendingIntent.getActivity(getActivity(), (int) System.currentTimeMillis(), intent, 0);
|
||||
|
||||
// build notification
|
||||
// the addAction re-use the same intent to keep the example short
|
||||
Notification n = new Notification.Builder(getActivity())
|
||||
.setContentTitle(getString(R.string.app_name))
|
||||
.setContentText(newDatabasePath + " saved!")
|
||||
.setSmallIcon(R.drawable.ic_launcher)
|
||||
.setContentIntent(pIntent)
|
||||
.setAutoCancel(true).build();
|
||||
|
||||
|
||||
NotificationManager notificationManager =
|
||||
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
|
||||
notificationManager.notify(0, n);
|
||||
}
|
||||
if(!mItemDataRecorderMode.isChecked())
|
||||
{
|
||||
mOpenedDatabasePath = newDatabasePath;
|
||||
}
|
||||
mProgressDialog.dismiss();
|
||||
updateState(State.STATE_IDLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
saveThread.start();
|
||||
saveDatabase(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1388,17 +1411,22 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
}
|
||||
else if(itemId == R.id.reset)
|
||||
{
|
||||
((TextView)findViewById(R.id.points)).setText(String.valueOf(0));
|
||||
((TextView)findViewById(R.id.polygons)).setText(String.valueOf(0));
|
||||
((TextView)findViewById(R.id.nodes)).setText(String.valueOf(0));
|
||||
((TextView)findViewById(R.id.words)).setText(String.valueOf(0));
|
||||
((TextView)findViewById(R.id.inliers)).setText(String.valueOf(0));
|
||||
((TextView)findViewById(R.id.features)).setText(String.valueOf(0));
|
||||
((TextView)findViewById(R.id.update_time)).setText(String.valueOf(0));
|
||||
((TextView)findViewById(R.id.hypothesis)).setText(String.valueOf(0));
|
||||
((TextView)findViewById(R.id.fps)).setText(String.valueOf(0));
|
||||
mTotalLoopClosures = 0;
|
||||
((TextView)findViewById(R.id.total_loop)).setText(String.valueOf(mTotalLoopClosures));
|
||||
|
||||
int index = 4;
|
||||
mStatusTexts[index++] = getString(R.string.nodes)+0;
|
||||
mStatusTexts[index++] = getString(R.string.words)+0;
|
||||
mStatusTexts[index++] = getString(R.string.database_size)+0;
|
||||
mStatusTexts[index++] = getString(R.string.points)+0;
|
||||
mStatusTexts[index++] = getString(R.string.polygons)+0;
|
||||
mStatusTexts[index++] = getString(R.string.update_time)+0;
|
||||
mStatusTexts[index++] = getString(R.string.features)+0;
|
||||
mStatusTexts[index++] = getString(R.string.rehearsal)+0;
|
||||
mStatusTexts[index++] = getString(R.string.total_loop)+0;
|
||||
mStatusTexts[index++] = getString(R.string.inliers)+0;
|
||||
mStatusTexts[index++] = getString(R.string.hypothesis)+0;
|
||||
mStatusTexts[index++] = getString(R.string.fps)+0;
|
||||
updateStatusTexts();
|
||||
|
||||
mOpenedDatabasePath = "";
|
||||
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
@@ -1422,17 +1450,21 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
// reset
|
||||
((TextView)findViewById(R.id.points)).setText(String.valueOf(0));
|
||||
((TextView)findViewById(R.id.polygons)).setText(String.valueOf(0));
|
||||
((TextView)findViewById(R.id.nodes)).setText(String.valueOf(0));
|
||||
((TextView)findViewById(R.id.words)).setText(String.valueOf(0));
|
||||
((TextView)findViewById(R.id.inliers)).setText(String.valueOf(0));
|
||||
((TextView)findViewById(R.id.features)).setText(String.valueOf(0));
|
||||
((TextView)findViewById(R.id.update_time)).setText(String.valueOf(0));
|
||||
((TextView)findViewById(R.id.hypothesis)).setText(String.valueOf(0));
|
||||
((TextView)findViewById(R.id.fps)).setText(String.valueOf(0));
|
||||
mTotalLoopClosures = 0;
|
||||
((TextView)findViewById(R.id.total_loop)).setText(String.valueOf(mTotalLoopClosures));
|
||||
int index = 4;
|
||||
mStatusTexts[index++] = getString(R.string.nodes)+0;
|
||||
mStatusTexts[index++] = getString(R.string.words)+0;
|
||||
mStatusTexts[index++] = getString(R.string.database_size)+0;
|
||||
mStatusTexts[index++] = getString(R.string.points)+0;
|
||||
mStatusTexts[index++] = getString(R.string.polygons)+0;
|
||||
mStatusTexts[index++] = getString(R.string.update_time)+0;
|
||||
mStatusTexts[index++] = getString(R.string.features)+0;
|
||||
mStatusTexts[index++] = getString(R.string.rehearsal)+0;
|
||||
mStatusTexts[index++] = getString(R.string.total_loop)+0;
|
||||
mStatusTexts[index++] = getString(R.string.inliers)+0;
|
||||
mStatusTexts[index++] = getString(R.string.hypothesis)+0;
|
||||
mStatusTexts[index++] = getString(R.string.fps)+0;
|
||||
updateStatusTexts();
|
||||
|
||||
mItemDataRecorderMode.setChecked(!dataRecorderOldState);
|
||||
RTABMapLib.setDataRecorderMode(mItemDataRecorderMode.isChecked());
|
||||
@@ -1467,7 +1499,8 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
})
|
||||
.show();
|
||||
}
|
||||
else if(itemId == R.id.export_point_cloud ||
|
||||
else if(itemId == R.id.export_point_cloud ||
|
||||
itemId == R.id.export_point_cloud_highrez ||
|
||||
itemId == R.id.export_mesh ||
|
||||
itemId == R.id.export_mesh_texture ||
|
||||
itemId == R.id.export_optimized_mesh ||
|
||||
@@ -1476,14 +1509,14 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
final boolean isOBJ = itemId == R.id.export_mesh_texture || itemId == R.id.export_optimized_mesh_texture;
|
||||
final String extension = isOBJ? ".obj" : ".ply";
|
||||
|
||||
final int polygons = Integer.parseInt(((TextView)findViewById(R.id.polygons)).getText().toString());
|
||||
|
||||
final boolean meshing = itemId != R.id.export_point_cloud;
|
||||
final boolean meshing = itemId != R.id.export_point_cloud && itemId != R.id.export_point_cloud_highrez;
|
||||
final boolean regenerateCloud = itemId == R.id.export_point_cloud_highrez;
|
||||
final boolean optimized = itemId == R.id.export_optimized_mesh || itemId == R.id.export_optimized_mesh_texture;
|
||||
|
||||
// get Export settings
|
||||
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
final float cloudVoxelSize = Float.parseFloat(sharedPref.getString(getString(R.string.pref_key_cloud_voxel), getString(R.string.pref_default_cloud_voxel)));
|
||||
final String cloudVoxelSizeStr = sharedPref.getString(getString(R.string.pref_key_cloud_voxel), getString(R.string.pref_default_cloud_voxel));
|
||||
final float cloudVoxelSize = Float.parseFloat(cloudVoxelSizeStr);
|
||||
final int textureSize = isOBJ?Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_texture_size), getString(R.string.pref_default_texture_size))):0;
|
||||
final int normalK = Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_normal_k), getString(R.string.pref_default_normal_k)));
|
||||
final float maxTextureDistance = Float.parseFloat(sharedPref.getString(getString(R.string.pref_key_max_texture_distance), getString(R.string.pref_default_max_texture_distance)));
|
||||
@@ -1511,6 +1544,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
final boolean success = RTABMapLib.exportMesh(
|
||||
tmpPath,
|
||||
cloudVoxelSize,
|
||||
regenerateCloud,
|
||||
meshing,
|
||||
textureSize,
|
||||
normalK,
|
||||
@@ -1527,6 +1561,11 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
public void run() {
|
||||
if(success)
|
||||
{
|
||||
if(!meshing && cloudVoxelSize>0.0f)
|
||||
{
|
||||
mToast.makeText(getActivity(), String.format("Cloud assembled and voxelized at %s m.", cloudVoxelSizeStr), mToast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
// Visualize the result?
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setCancelable(false)
|
||||
@@ -1563,6 +1602,10 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
saveOnDevice();
|
||||
}
|
||||
})
|
||||
.setNeutralButton("Cancel", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
})
|
||||
@@ -1596,11 +1639,11 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
builder.setTitle("Choose Your File (*.db)");
|
||||
builder.setItems(filesWithSize, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, final int which) {
|
||||
|
||||
// Smooth and adjust color now?
|
||||
|
||||
// Adjust color now?
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setTitle("Opening database...")
|
||||
.setMessage("Do you want to smooth and adjust colors now?\nThis can be done later under Optimize menu.")
|
||||
.setMessage("Do you want to adjust colors now?\nThis can be done later under Optimize menu.")
|
||||
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichIn) {
|
||||
openDatabase(files[which], true);
|
||||
@@ -1633,6 +1676,67 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void saveDatabase(String fileName)
|
||||
{
|
||||
final String newDatabasePath = mWorkingDirectory + fileName + ".db";
|
||||
final String newDatabasePathHuman = mWorkingDirectoryHuman + fileName + ".db";
|
||||
mProgressDialog.setTitle("Saving");
|
||||
if(mOpenedDatabasePath.equals(newDatabasePath))
|
||||
{
|
||||
mProgressDialog.setMessage(String.format("Please wait while updating \"%s\"...", newDatabasePathHuman));
|
||||
}
|
||||
else
|
||||
{
|
||||
mProgressDialog.setMessage(String.format("Please wait while saving \"%s\"...", newDatabasePathHuman));
|
||||
}
|
||||
mProgressDialog.show();
|
||||
updateState(State.STATE_PROCESSING);
|
||||
startUpdateStatusThread();
|
||||
Thread saveThread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
RTABMapLib.save(newDatabasePath); // save
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
if(mOpenedDatabasePath.equals(newDatabasePath))
|
||||
{
|
||||
mToast.makeText(getActivity(), String.format("Database \"%s\" updated.", newDatabasePathHuman), mToast.LENGTH_LONG).show();
|
||||
}
|
||||
else
|
||||
{
|
||||
mToast.makeText(getActivity(), String.format("Database saved to \"%s\".", newDatabasePathHuman), mToast.LENGTH_LONG).show();
|
||||
|
||||
Intent intent = new Intent(getActivity(), RTABMapActivity.class);
|
||||
// use System.currentTimeMillis() to have a unique ID for the pending intent
|
||||
PendingIntent pIntent = PendingIntent.getActivity(getActivity(), (int) System.currentTimeMillis(), intent, 0);
|
||||
|
||||
// build notification
|
||||
// the addAction re-use the same intent to keep the example short
|
||||
Notification n = new Notification.Builder(getActivity())
|
||||
.setContentTitle(getString(R.string.app_name))
|
||||
.setContentText(newDatabasePathHuman + " saved!")
|
||||
.setSmallIcon(R.drawable.ic_launcher)
|
||||
.setContentIntent(pIntent)
|
||||
.setAutoCancel(true).build();
|
||||
|
||||
|
||||
NotificationManager notificationManager =
|
||||
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
|
||||
notificationManager.notify(0, n);
|
||||
}
|
||||
if(!mItemDataRecorderMode.isChecked())
|
||||
{
|
||||
mOpenedDatabasePath = newDatabasePath;
|
||||
}
|
||||
mProgressDialog.dismiss();
|
||||
updateState(State.STATE_IDLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
saveThread.start();
|
||||
}
|
||||
|
||||
private void saveOnDevice()
|
||||
{
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
@@ -1705,6 +1809,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
{
|
||||
final String extension = mExportedOBJ?".obj":".ply";
|
||||
final String path = mWorkingDirectory + fileName + extension;
|
||||
final String pathHuman = mWorkingDirectoryHuman + fileName + extension;
|
||||
|
||||
boolean success = true;
|
||||
if(mExportedOBJ)
|
||||
@@ -1726,28 +1831,28 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
copy(fromOBJFile,toOBJFile);
|
||||
copy(fromMTLFile,toMTLFile);
|
||||
copy(fromJPGFile,toJPGFile);
|
||||
mToast.makeText(getActivity(), String.format("Mesh \"%s\" (with texture \"%s\" and \"%s\") successfully exported!", path, fileName + ".jpg", fileName + ".mtl"), mToast.LENGTH_LONG).show();
|
||||
mToast.makeText(getActivity(), String.format("Mesh \"%s\" (with texture \"%s\" and \"%s\") successfully exported!", pathHuman, fileName + ".jpg", fileName + ".mtl"), mToast.LENGTH_LONG).show();
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
mToast.makeText(getActivity(), String.format("Exporting mesh \"%s\" (with texture \"%s\" and \"%s\") failed! Error=%s", path, fileName + ".jpg", fileName + ".mtl", e.getMessage()), mToast.LENGTH_LONG).show();
|
||||
mToast.makeText(getActivity(), String.format("Exporting mesh \"%s\" (with texture \"%s\" and \"%s\") failed! Error=%s", pathHuman, fileName + ".jpg", fileName + ".mtl", e.getMessage()), mToast.LENGTH_LONG).show();
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
File toPLYFile = new File(mWorkingDirectory + fileName + extension);
|
||||
File toPLYFile = new File(path);
|
||||
toPLYFile.delete();
|
||||
File fromPLYFile = new File(mWorkingDirectory + RTABMAP_TMP_DIR + RTABMAP_TMP_FILENAME + extension);
|
||||
|
||||
try
|
||||
{
|
||||
copy(fromPLYFile,toPLYFile);
|
||||
mToast.makeText(getActivity(), String.format("Mesh/point cloud \"%s\" successfully exported!", path), mToast.LENGTH_LONG).show();
|
||||
mToast.makeText(getActivity(), String.format("Mesh/point cloud \"%s\" successfully exported!", pathHuman), mToast.LENGTH_LONG).show();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mToast.makeText(getActivity(), String.format("Exporting mesh/point cloud \"%s\" failed! Error=%s", path, e.getMessage()), mToast.LENGTH_LONG).show();
|
||||
mToast.makeText(getActivity(), String.format("Exporting mesh/point cloud \"%s\" failed! Error=%s", pathHuman, e.getMessage()), mToast.LENGTH_LONG).show();
|
||||
success=false;
|
||||
}
|
||||
}
|
||||
@@ -1762,7 +1867,7 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
// the addAction re-use the same intent to keep the example short
|
||||
Notification n = new Notification.Builder(getActivity())
|
||||
.setContentTitle(getString(R.string.app_name))
|
||||
.setContentText(path + " exported!")
|
||||
.setContentText(pathHuman + " exported!")
|
||||
.setSmallIcon(R.drawable.ic_launcher)
|
||||
.setContentIntent(pIntent)
|
||||
.setAutoCancel(true).build();
|
||||
@@ -1775,19 +1880,11 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
}
|
||||
}
|
||||
|
||||
private void openDatabase(String fileName, boolean optimize)
|
||||
private void openDatabase(final String fileName, final boolean optimize)
|
||||
{
|
||||
mOpenedDatabasePath = mWorkingDirectory + fileName;
|
||||
|
||||
if(!mItemTrajectoryMode.isChecked())
|
||||
{
|
||||
mProgressDialog.setTitle("Loading");
|
||||
mProgressDialog.setMessage(String.format("Database \"%s\" loaded. Please wait while creating point clouds and meshes...", fileName));
|
||||
mProgressDialog.show();
|
||||
updateState(State.STATE_PROCESSING);
|
||||
}
|
||||
|
||||
String tmpDatabase = mWorkingDirectory+RTABMAP_TMP_DB;
|
||||
final String tmpDatabase = mWorkingDirectory+RTABMAP_TMP_DB;
|
||||
(new File(tmpDatabase)).delete();
|
||||
try{
|
||||
copy(new File(mOpenedDatabasePath), new File(tmpDatabase));
|
||||
@@ -1798,32 +1895,62 @@ public class RTABMapActivity extends Activity implements OnClickListener {
|
||||
}
|
||||
|
||||
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||
boolean databaseInMemory = sharedPref.getBoolean(getString(R.string.pref_key_db_in_memory), Boolean.parseBoolean(getString(R.string.pref_default_db_in_memory)));
|
||||
int status = RTABMapLib.openDatabase(tmpDatabase, databaseInMemory, optimize);
|
||||
setCamera(1);
|
||||
updateState(State.STATE_IDLE);
|
||||
final boolean databaseInMemory = sharedPref.getBoolean(getString(R.string.pref_key_db_in_memory), Boolean.parseBoolean(getString(R.string.pref_default_db_in_memory)));
|
||||
|
||||
if(status == -1)
|
||||
{
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setCancelable(false)
|
||||
.setTitle("Error")
|
||||
.setMessage("The map is loaded but optimization of the map's graph has "
|
||||
+ "failed, so the map cannot be shown. Change the Graph Optimizer approach used"
|
||||
+ " or enable/disable if the graph is optimized from graph "
|
||||
+ "end in \"Settings -> Mapping...\" and try opening again.")
|
||||
.setPositiveButton("Open Settings", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent intent = new Intent(getActivity(), SettingsActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
})
|
||||
.setNegativeButton("Close", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
mProgressDialog.setTitle("Loading");
|
||||
mProgressDialog.setMessage(String.format("Opening database \"%s\"...", fileName));
|
||||
mProgressDialog.show();
|
||||
updateState(State.STATE_PROCESSING);
|
||||
|
||||
Thread openThread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
|
||||
final int status = RTABMapLib.openDatabase(tmpDatabase, databaseInMemory, optimize);
|
||||
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
setCamera(1);
|
||||
updateState(State.STATE_IDLE);
|
||||
mProgressDialog.dismiss();
|
||||
if(status == -1)
|
||||
{
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setCancelable(false)
|
||||
.setTitle("Error")
|
||||
.setMessage("The map is loaded but optimization of the map's graph has "
|
||||
+ "failed, so the map cannot be shown. Change the Graph Optimizer approach used"
|
||||
+ " or enable/disable if the graph is optimized from graph "
|
||||
+ "end in \"Settings -> Mapping...\" and try opening again.")
|
||||
.setPositiveButton("Open Settings", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent intent = new Intent(getActivity(), SettingsActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
})
|
||||
.setNegativeButton("Close", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
else
|
||||
{
|
||||
// creating meshes...
|
||||
startUpdateStatusThread();
|
||||
|
||||
if(!mItemTrajectoryMode.isChecked())
|
||||
{
|
||||
mProgressDialog.setTitle("Loading");
|
||||
mProgressDialog.setMessage(String.format("Database \"%s\" loaded. Please wait while creating point clouds and meshes...", fileName));
|
||||
mProgressDialog.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
openThread.start();
|
||||
}
|
||||
|
||||
public void copy(File src, File dst) throws IOException {
|
||||
|
||||
Reference in New Issue
Block a user