RTABMapActivity.java
Go to the documentation of this file.
1 package com.introlab.rtabmap;
2 
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.FileNotFoundException;
6 import java.io.FileOutputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.OutputStream;
10 import java.lang.reflect.InvocationTargetException;
11 import java.lang.reflect.Method;
12 import java.text.SimpleDateFormat;
13 import java.util.ArrayList;
14 import java.util.Arrays;
15 import java.util.Date;
16 import java.util.HashMap;
17 import java.util.Timer;
18 import java.util.TimerTask;
19 
20 import android.Manifest;
21 import android.app.ActivityManager;
22 import android.app.ActivityManager.MemoryInfo;
23 import android.app.AlertDialog;
24 import android.app.Notification;
25 import android.app.NotificationManager;
26 import android.app.PendingIntent;
27 import android.app.ProgressDialog;
28 import android.content.ComponentName;
29 import android.content.ContentResolver;
30 import android.content.ContentValues;
31 import android.content.Context;
32 import android.content.DialogInterface;
33 import android.content.DialogInterface.OnShowListener;
34 import android.content.Intent;
35 import android.content.ServiceConnection;
36 import android.content.SharedPreferences;
37 import android.content.pm.ApplicationInfo;
38 import android.content.pm.PackageInfo;
39 import android.content.pm.PackageManager;
40 import android.content.pm.PackageManager.NameNotFoundException;
41 import android.database.Cursor;
42 import android.hardware.Camera;
43 import android.hardware.Sensor;
44 import android.hardware.SensorEvent;
45 import android.hardware.SensorEventListener;
46 import android.hardware.SensorManager;
47 import android.graphics.Matrix;
48 import android.graphics.Point;
49 import android.hardware.display.DisplayManager;
50 import android.location.Location;
51 import android.location.LocationListener;
52 import android.location.LocationManager;
53 import android.media.MediaScannerConnection;
54 import android.net.Uri;
55 import android.net.wifi.WifiInfo;
56 import android.net.wifi.WifiManager;
57 import android.opengl.GLSurfaceView;
58 import android.os.Bundle;
59 import android.os.Environment;
60 import android.os.Handler;
61 import android.os.IBinder;
62 import android.os.Message;
63 import android.preference.PreferenceManager;
64 import android.provider.MediaStore;
65 import android.provider.OpenableColumns;
66 import android.support.v4.app.FragmentActivity;
67 import android.support.v4.content.FileProvider;
68 import android.text.InputType;
69 import android.util.Log;
70 import android.util.TypedValue;
71 import android.view.ContextMenu;
72 import android.view.Display;
73 import android.view.GestureDetector;
74 import android.view.Menu;
75 import android.view.MenuItem;
76 import android.view.MenuItem.OnMenuItemClickListener;
77 import android.view.MenuInflater;
78 import android.view.MotionEvent;
79 import android.view.View;
80 import android.view.ContextMenu.ContextMenuInfo;
81 import android.view.View.OnClickListener;
82 import android.view.View.OnCreateContextMenuListener;
83 import android.view.View.OnTouchListener;
84 import android.view.WindowManager;
85 import android.view.inputmethod.EditorInfo;
86 import android.widget.AdapterView;
87 import android.widget.AdapterView.OnItemSelectedListener;
88 import android.widget.ArrayAdapter;
89 import android.widget.Button;
90 import android.widget.EditText;
91 import android.widget.ImageButton;
92 import android.widget.ListView;
93 import android.widget.NumberPicker;
94 import android.widget.RelativeLayout;
95 import android.widget.SeekBar;
96 import android.widget.SeekBar.OnSeekBarChangeListener;
97 import android.widget.Toast;
98 import android.widget.ToggleButton;
99 
100 import com.google.ar.core.ArCoreApk;
101 import com.google.atap.tangoservice.Tango;
102 import com.huawei.hiar.AREnginesApk;
103 
104 
105 // The main activity of the application. This activity shows debug information
106 // and a glSurfaceView that renders graphic content.
107 public class RTABMapActivity extends FragmentActivity implements OnClickListener, OnItemSelectedListener, SensorEventListener {
108 
109  // Opaque native pointer to the native application instance.
110  public static long nativeApplication;
111 
112  // Tag for debug logging.
113  public static final String TAG = RTABMapActivity.class.getSimpleName();
114  public static boolean DISABLE_LOG = false;
115 
116  // The minimum Tango Core version required from this application.
117  private static final int MIN_TANGO_CORE_VERSION = 9377;
118 
119  // The package name of Tang Core, used for checking minimum Tango Core version.
120  private static final String TANGO_PACKAGE_NAME = "com.google.tango";
121 
122  public static final String EXTRA_KEY_PERMISSIONTYPE = "PERMISSIONTYPE";
123  public static final String EXTRA_VALUE_ADF = "ADF_LOAD_SAVE_PERMISSION";
124 
125  public static final String RTABMAP_TMP_DB = "rtabmap.tmp.db";
126  public static final String RTABMAP_TMP_DIR = "tmp";
127  public static final String RTABMAP_TMP_FILENAME = "map";
128  public static final String RTABMAP_SDCARD_PATH = "/Internal storage/";
129  public static final String RTABMAP_EXPORT_DIR = "Export/";
130 
131  public static final String RTABMAP_AUTH_TOKEN_KEY = "com.introlab.rtabmap.AUTH_TOKEN";
132  public static final String RTABMAP_FILENAME_KEY = "com.introlab.rtabmap.FILENAME";
133  public static final String RTABMAP_OPENED_DB_PATH_KEY = "com.introlab.rtabmap.OPENED_DB_PATH";
134  public static final String RTABMAP_WORKING_DIR_KEY = "com.introlab.rtabmap.WORKING_DIR";
135  public static final int SKETCHFAB_ACTIVITY_CODE = 999;
136  private String mAuthToken;
137 
138  public static final long NOTOUCH_TIMEOUT = 5000; // 5 sec
139  private boolean mHudVisible = true;
140  private int mSavedRenderingType = 0;
141  private boolean mMenuOpened = false;
142  private long mSavedStamp = 0;
143 
144  // UI states
145  private static enum State {
146  STATE_WELCOME, // Camera/Motion off - showing only buttons open and start new scan
147  STATE_CAMERA, // Camera/Motion on - not mapping
148  STATE_MAPPING, // Camera/Motion on - mapping
149  STATE_IDLE, // Camera/Motion off
150  STATE_PROCESSING, // Camera/Motion off - post processing
151  STATE_VISUALIZING, // Camera/Motion off - Showing optimized mesh
152  STATE_VISUALIZING_CAMERA, // Camera/Motion on - Showing optimized mesh
153  STATE_VISUALIZING_WHILE_LOADING // Camera/Motion off - Loading data while showing optimized mesh
154  }
155  State mState = State.STATE_WELCOME;
156 
157  // GLSurfaceView and renderer, all of the graphic content is rendered
158  // through OpenGL ES 2.0 in native code.
159  private Renderer mRenderer = null;
160  private GLSurfaceView mGLView;
161 
162  View mDecorView;
163  int mStatusBarHeight = 0;
164  int mActionBarHeight = 0;
165 
166  ProgressDialog mProgressDialog;
167  ProgressDialog mExportProgressDialog;
168 
169  // Screen size for normalizing the touch input for orbiting the render camera.
170  private Point mScreenSize = new Point();
171  private Date mBackClickedTime = new Date();
172  private long mOnPauseStamp = 0;
173  private boolean mOnPause = false;
174  private Date mDateOnPause = new Date();
176  private long mFreeMemoryOnStart = 0;
177 
178  private MenuItem mItemSave;
179  private MenuItem mItemOpen;
180  private MenuItem mItemNewScan;
181  private MenuItem mItemPostProcessing;
182  private MenuItem mItemExport;
183  private MenuItem mItemSettings;
184  private MenuItem mItemModes;
185  private MenuItem mItemResume;
186  private MenuItem mItemLocalizationMode;
187  private MenuItem mItemTrajectoryMode;
188  private MenuItem mItemRenderingPointCloud;
189  private MenuItem mItemRenderingMesh;
190  private MenuItem mItemRenderingTextureMesh;
191  private MenuItem mItemDataRecorderMode;
192  private MenuItem mItemStatusVisibility;
193  private MenuItem mItemDebugVisibility;
194 
196  private ImageButton mButtonStart;
197  private ImageButton mButtonStop;
198  private ToggleButton mButtonLighting;
199  private ToggleButton mButtonWireframe;
200  private ToggleButton mButtonBackfaceShown;
202  private Button mButtonSaveOnDevice;
203  private Button mButtonShareOnSketchfab;
204  private Button mButtonLibrary;
205  private Button mButtonNewScan;
206  private SeekBar mSeekBarOrthoCut;
207  private SeekBar mSeekBarGrid;
208 
209  private String mOpenedDatabasePath = "";
210  private String mWorkingDirectory = "";
211  private String mWorkingDirectoryHuman = "";
212 
213  private String mUpdateRate;
214  private String mTimeThr;
215  private String mMaxFeatures;
216  private String mLoopThr;
217  private String mMinInliers;
218  private String mMaxOptimizationError;
219  private boolean mGPSSaved = false;
220  private boolean mEnvSensorsSaved = false;
221  private boolean mIsARCoreAvailable = false;
222  private boolean mIsAREngineAvailable = false;
223 
224  private LocationManager mLocationManager;
225  private LocationListener mLocationListener;
226  private Location mLastKnownLocation;
227  private SensorManager mSensorManager;
228  private WifiManager mWifiManager;
229  private Timer mEnvSensorsTimer = new Timer();
230  Sensor mAccelerometer;
231  Sensor mMagnetometer;
232  Sensor mAmbientTemperature;
233  Sensor mAmbientLight;
234  Sensor mAmbientAirPressure;
235  Sensor mAmbientRelativeHumidity;
236  private float mCompassDeg = 0.0f;
237  private float[] mLastEnvSensors = new float[5];
238  private boolean[] mLastEnvSensorsSet = new boolean[5];
239 
240  private float[] mLastAccelerometer = new float[3];
241  private float[] mLastMagnetometer = new float[3];
242  private boolean mLastAccelerometerSet = false;
243  private boolean mLastMagnetometerSet = false;
244 
245  private Matrix mDeviceToCamera = new Matrix();
246  private Matrix mRMat = new Matrix();
247  private Matrix mNewR = new Matrix();
248  private float[] mR = new float[9];
249  private float[] mOrientation = new float[3];
250 
251  private int mTotalLoopClosures = 0;
252  int mMapNodes = 0;
253 
254  private Toast mToast = null;
255 
256  private AlertDialog mMemoryWarningDialog = null;
257 
258  private final int STATUS_TEXTS_SIZE = 20;
259  private final int STATUS_TEXTS_POSE_INDEX = 6;
260  private String[] mStatusTexts = new String[STATUS_TEXTS_SIZE];
261 
262  GestureDetector mGesDetect = null;
263 
264  ARCoreSharedCamera mArCoreCamera = null;
265  int mCameraDriver = 0;
266 
267  private String mIntentDbToOpen = null;
268 
269  //Tango Service connection.
270  boolean mCameraServiceConnectionUsed = false;
271  ServiceConnection mCameraServiceConnection = new ServiceConnection() {
272  public void onServiceConnected(ComponentName name, final IBinder service) {
273  Thread bindThread = new Thread(new Runnable() {
274  public void run() {
275  final boolean cameraStartSucess = RTABMapLib.startCamera(nativeApplication, service, getApplicationContext(), getActivity(), mCameraDriver);
276  runOnUiThread(new Runnable() {
277  public void run() {
278  mProgressDialog.dismiss();
279  if(!cameraStartSucess)
280  {
281  mToast.makeText(getApplicationContext(),
282  String.format("Failed to intialize Tango camera! RTAB-Map may not be built with Tango support."), mToast.LENGTH_LONG).show();
283  if(mCameraServiceConnectionUsed)
284  {
285  if(!DISABLE_LOG) Log.i(TAG, String.format("unbindService"));
286  getActivity().unbindService(mCameraServiceConnection);
287  }
288  mCameraServiceConnectionUsed = false;
289  }
290  else
291  {
293  if(mState==State.STATE_VISUALIZING_CAMERA && mItemLocalizationMode.isChecked())
294  {
296  }
297  }
298  }
299  });
300  }
301  });
302  bindThread.start();
303  }
304 
305  public void onServiceDisconnected(ComponentName name) {
306  // Handle this if you need to gracefully shutdown/retry
307  // in the event that Tango itself crashes/gets upgraded while running.
308  mToast.makeText(getApplicationContext(),
309  String.format("Tango disconnected!"), mToast.LENGTH_LONG).show();
310  }
311  };
312 
313  @Override
314  protected void onCreate(Bundle savedInstanceState) {
315  super.onCreate(savedInstanceState);
316  setTitle(R.string.menu_name);
317 
319 
321 
322  // Query screen size, the screen size is used for computing the normalized
323  // touch point.
324  Display display = getWindowManager().getDefaultDisplay();
325  display.getSize(mScreenSize);
326  Log.i(TAG, String.format("Screen resolution: %dx%d", mScreenSize.x, mScreenSize.y));
327 
328  getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
329  getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
330 
331  // Setting content view of this activity.
332  setContentView(R.layout.activity_rtabmap);
333 
334  // Make sure to initialize all default values
335  SettingsActivity settings;
336 
337  mDecorView = getWindow().getDecorView();
338  mStatusBarHeight = getStatusBarHeight();
339  mActionBarHeight = getActionBarHeight();
340 
341  // Buttons for selecting camera view and Set up button click listeners.
342  mButtonCameraView = (NDSpinner)findViewById(R.id.camera_button);
343  mButtonStart = (ImageButton)findViewById(R.id.start_button);
344  mButtonStop = (ImageButton)findViewById(R.id.stop_button);
345  mButtonLighting = (ToggleButton)findViewById(R.id.light_button);
346  mButtonWireframe = (ToggleButton)findViewById(R.id.wireframe_button);
347  mButtonBackfaceShown = (ToggleButton)findViewById(R.id.backface_button);
348  mButtonCloseVisualization = (Button)findViewById(R.id.close_visualization_button);
349  mButtonSaveOnDevice = (Button)findViewById(R.id.button_saveOnDevice);
350  mButtonShareOnSketchfab = (Button)findViewById(R.id.button_shareToSketchfab);
351  mButtonLibrary = (Button)findViewById(R.id.button_library);
352  mButtonNewScan = (Button)findViewById(R.id.button_new_scan);
353  mButtonCameraView.setOnItemSelectedListener(this);
354  mButtonStart.setOnClickListener(this);
355  mButtonStop.setOnClickListener(this);
356  mButtonLighting.setOnClickListener(this);
357  mButtonWireframe.setOnClickListener(this);
358  mButtonBackfaceShown.setOnClickListener(this);
359  mButtonCloseVisualization.setOnClickListener(this);
360  mButtonSaveOnDevice.setOnClickListener(this);
361  mButtonShareOnSketchfab.setOnClickListener(this);
362  mButtonLibrary.setOnClickListener(this);
363  mButtonNewScan.setOnClickListener(this);
364  mButtonLighting.setChecked(false);
365  mButtonLighting.setVisibility(View.INVISIBLE);
366  mButtonWireframe.setChecked(false);
367  mButtonWireframe.setVisibility(View.INVISIBLE);
368  mButtonCloseVisualization.setVisibility(View.INVISIBLE);
369  mButtonSaveOnDevice.setVisibility(View.INVISIBLE);
370  mButtonShareOnSketchfab.setVisibility(View.INVISIBLE);
371  mButtonLibrary.setVisibility(View.INVISIBLE);
372  mButtonNewScan.setVisibility(View.INVISIBLE);
373  if(mItemRenderingMesh != null && mItemRenderingTextureMesh != null)
374  {
375  mButtonBackfaceShown.setVisibility(mItemRenderingMesh.isChecked() || mItemRenderingTextureMesh.isChecked()?View.VISIBLE:View.INVISIBLE);
376  }
377 
378  ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.camera_view_array, android.R.layout.simple_spinner_item);
379  adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
380  mButtonCameraView.setAdapter(adapter);
381  mButtonCameraView.setOnTouchListener(new OnTouchListener() {
382  @Override
383  public boolean onTouch(View v, MotionEvent event) {
385  return false;
386  }
387  });
388 
389  mSeekBarOrthoCut = (SeekBar)findViewById(R.id.seekBar_ortho_cut);
390  mSeekBarOrthoCut.setMax(120);
391  mSeekBarOrthoCut.setProgress(80);
392  mSeekBarOrthoCut.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
393  @Override
394  public void onProgressChanged(SeekBar seekBar, int progressValue, boolean fromUser) {
395  RTABMapLib.setOrthoCropFactor(nativeApplication, (float)(120-progressValue)/20.0f - 3.0f);
397  }
398 
399  @Override
400  public void onStartTrackingTouch(SeekBar seekBar) {
401  }
402 
403  @Override
404  public void onStopTrackingTouch(SeekBar seekBar) {
405  }
406  });
407 
408  mSeekBarGrid = (SeekBar)findViewById(R.id.seekBar_grid);
409  mSeekBarGrid.setMax(180);
410  mSeekBarGrid.setProgress(90);
411  mSeekBarGrid.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
412  @Override
413  public void onProgressChanged(SeekBar seekBar, int progressValue, boolean fromUser) {
414  RTABMapLib.setGridRotation(nativeApplication, ((float)progressValue-90.0f)/2.0f);
416  }
417 
418  @Override
419  public void onStartTrackingTouch(SeekBar seekBar) {
420  }
421 
422  @Override
423  public void onStopTrackingTouch(SeekBar seekBar) {
424  }
425  });
426 
427  mToast = Toast.makeText(getApplicationContext(), "", Toast.LENGTH_SHORT);
428 
429  // OpenGL view where all of the graphics are drawn.
430  mGLView = (GLSurfaceView) findViewById(R.id.gl_surface_view);
431 
432  mGesDetect = new GestureDetector(this, new DoubleTapGestureDetector());
433 
434  // Configure OpenGL renderer
435  mGLView.setEGLContextClientVersion(2);
436  mGLView.setEGLConfigChooser(8, 8, 8, 8, 24, 0);
437  mGLView.setOnTouchListener(new OnTouchListener() {
438  @Override
439  public boolean onTouch(View v, MotionEvent event) {
440 
441  resetNoTouchTimer(getActionBar().isShowing() && mHudVisible == false);
442 
443  mGesDetect.onTouchEvent(event);
444 
445  // Pass the touch event to the native layer for camera control.
446  // Single touch to rotate the camera around the device.
447  // Two fingers to zoom in and out.
448  int pointCount = event.getPointerCount();
449  if (pointCount == 1) {
450  float normalizedX = event.getX(0) / mScreenSize.x;
451  float normalizedY = event.getY(0) / mScreenSize.y;
453  event.getActionMasked(), normalizedX, normalizedY, 0.0f, 0.0f);
454  }
455  if (pointCount == 2) {
456  if (event.getActionMasked() == MotionEvent.ACTION_POINTER_UP) {
457  int index = event.getActionIndex() == 0 ? 1 : 0;
458  float normalizedX = event.getX(index) / mScreenSize.x;
459  float normalizedY = event.getY(index) / mScreenSize.y;
461  MotionEvent.ACTION_DOWN, normalizedX, normalizedY, 0.0f, 0.0f);
462  } else {
463  float normalizedX0 = event.getX(0) / mScreenSize.x;
464  float normalizedY0 = event.getY(0) / mScreenSize.y;
465  float normalizedX1 = event.getX(1) / mScreenSize.x;
466  float normalizedY1 = event.getY(1) / mScreenSize.y;
467  RTABMapLib.onTouchEvent(nativeApplication, 2, event.getActionMasked(),
468  normalizedX0, normalizedY0, normalizedX1, normalizedY1);
469  }
470  }
471  return true;
472  }
473  });
474 
475  // Configure the OpenGL renderer.
476  mRenderer = new Renderer(this);
477  mGLView.setRenderer(mRenderer);
478 
479  mProgressDialog = new ProgressDialog(this);
480  mProgressDialog.setCanceledOnTouchOutside(false);
481  mRenderer.setProgressDialog(mProgressDialog);
483  setNavVisibility(true);
484 
485  mExportProgressDialog = new ProgressDialog(this);
486  mExportProgressDialog.setCanceledOnTouchOutside(false);
487  mExportProgressDialog.setCancelable(false);
488  mExportProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
489  mExportProgressDialog.setProgressNumberFormat(null);
490  mExportProgressDialog.setProgressPercentFormat(null);
491  mExportProgressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
492  @Override
493  public void onClick(DialogInterface dialog, int which) {
494  RTABMapLib.cancelProcessing(nativeApplication);
495 
496  mProgressDialog.setTitle("");
497  mProgressDialog.setMessage(String.format("Cancelling..."));
498  mProgressDialog.show();
499  }
500  });
501 
502  mOpenedDatabasePath = "";
503  mWorkingDirectory = "";
505  mTotalLoopClosures = 0;
506  mLastFastMovementNotificationStamp = System.currentTimeMillis()/1000;
507 
508 
509  int targetSdkVersion= 0;
510  try {
511  ApplicationInfo app = this.getPackageManager().getApplicationInfo("com.introlab.rtabmap", 0);
512  targetSdkVersion = app.targetSdkVersion;
513  } catch (NameNotFoundException e) {
514  e.printStackTrace();
515  }
516 
517  if(Environment.getExternalStorageState().compareTo(Environment.MEDIA_MOUNTED)==0 &&
518  (targetSdkVersion < 30 || getActivity().getExternalFilesDirs(null).length >=1))
519  {
520  File extStore;
521  if(targetSdkVersion < 30)
522  {
523  extStore = Environment.getExternalStorageDirectory();
524  }
525  else // >= android30
526  {
527  extStore = getActivity().getExternalFilesDirs(null)[0];
528  }
529 
530  mWorkingDirectory = extStore.getAbsolutePath() + "/" + getString(R.string.app_name) + "/";
531  extStore = new File(mWorkingDirectory);
532  extStore.mkdirs();
533  mWorkingDirectoryHuman = RTABMAP_SDCARD_PATH + getString(R.string.app_name) + "/";
534  }
535  else
536  {
537  // show warning that data cannot be saved!
538  mToast.makeText(getApplicationContext(),
539  String.format("Failed to get external storage path (state=%s). Saving disabled.",
540  Environment.getExternalStorageState()), mToast.LENGTH_LONG).show();
541  }
542 
543  DisplayManager displayManager = (DisplayManager) getSystemService(DISPLAY_SERVICE);
544  if (displayManager != null) {
545  displayManager.registerDisplayListener(new DisplayManager.DisplayListener() {
546  @Override
547  public void onDisplayAdded(int displayId) {
548 
549  }
550 
551  @Override
552  public void onDisplayChanged(int displayId) {
553  synchronized (this) {
555  Display display = getWindowManager().getDefaultDisplay();
556  display.getSize(mScreenSize);
557  }
558  }
559 
560  @Override
561  public void onDisplayRemoved(int displayId) {}
562  }, null);
563  }
564 
565  // Acquire a reference to the system Location Manager
566  mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
567 
568  // Define a listener that responds to location updates
569  mLocationListener = new LocationListener() {
570  public void onLocationChanged(Location location) {
571  mLastKnownLocation = location;
572  double stamp = location.getTime()/1000.0;
573  if(!DISABLE_LOG) Log.d(TAG, String.format("GPS received at %f (%d)", stamp, location.getTime()));
574  RTABMapLib.setGPS(
576  stamp,
577  (double)location.getLongitude(),
578  (double)location.getLatitude(),
579  (double)location.getAltitude(),
580  (double)location.getAccuracy(),
581  (double)mCompassDeg);
582  }
583 
584  public void onStatusChanged(String provider, int status, Bundle extras) {}
585 
586  public void onProviderEnabled(String provider) {}
587 
588  public void onProviderDisabled(String provider) {}
589  };
590 
591  mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
592  mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
593  mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
594  mAmbientTemperature = mSensorManager.getDefaultSensor(Sensor.TYPE_AMBIENT_TEMPERATURE);
595  mAmbientLight = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
596  mAmbientAirPressure = mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);
597  mAmbientRelativeHumidity = mSensorManager.getDefaultSensor(Sensor.TYPE_RELATIVE_HUMIDITY);
598  float [] values = {1,0,0,0,0,1,0,-1,0};
599  mDeviceToCamera.setValues(values);
600  mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
601 
602  setCamera(1);
603 
604  DISABLE_LOG = !( 0 != ( getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE ) );
605 
606  SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
607  String cameraDriverStr = sharedPref.getString(getString(R.string.pref_key_camera_driver), getString(R.string.pref_default_camera_driver));
608  mCameraDriver = Integer.parseInt(cameraDriverStr);
609 
612 
613  if (!PermissionHelper.hasPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
614  PermissionHelper.requestPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
615  }
616  else
617  {
618  // Get intent, action and MIME type
619  Intent intent = getIntent();
620  String action = intent.getAction();
621  String type = intent.getType();
622 
623  if (Intent.ACTION_SEND.equals(action) && type != null) {
624  if ("application/octet-stream".equals(type)) {
625  Uri imageUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
626  if (imageUri != null) {
627  String fileName = getFileName(imageUri);
628  Log.i(TAG, "Intent received: " + imageUri.getPath() + " Name:" + fileName);
629  if(fileName.endsWith(".db"))
630  {
631  File file = new File(mWorkingDirectory+fileName);
632  if(file.exists())
633  {
634  mToast.makeText(this, fileName + " already exists in RTAB-Map's library! Cannot be copied.", mToast.LENGTH_LONG).show();
635  }
636  else
637  {
638  copy(imageUri, file);
639  mIntentDbToOpen = fileName;
640  }
641  }
642  }
643  }
644  } else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
645  if (type.startsWith("application/")) {
646  ArrayList<Uri> imageUris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
647  if (imageUris != null) {
648  boolean added = false;
649  for(Uri imageUri: imageUris)
650  {
651  String fileName = getFileName(imageUri);
652  Log.i(TAG, "Intent received: " + imageUri.getPath() + " Name:" + fileName);
653  if(fileName.endsWith(".db"))
654  {
655  File file = new File(mWorkingDirectory+"/"+getFileName(imageUri));
656  if(!file.exists())
657  {
658  copy(imageUri, file);
659  added = true;
660  }
661  else
662  {
663  Log.e(TAG, fileName + " already exists in RTAB-Map's library! Cannot be copied.");
664  }
665  }
666  }
667  if(added)
668  {
669  openDatabase();
670  }
671  }
672 
673  }
674  }
675 
676  postCreate();
677  }
678  }
679 
680  public void copy(File src, File dst) throws IOException {
681  InputStream in = new FileInputStream(src);
682  OutputStream out = new FileOutputStream(dst);
683 
684  // Transfer bytes from in to out
685  byte[] buf = new byte[1024];
686  int len;
687  while ((len = in.read(buf)) > 0) {
688  out.write(buf, 0, len);
689  }
690  in.close();
691  out.close();
692  }
693 
694  public void copy(Uri uri, File file)
695  {
696  InputStream in;
697  try {
698  in = getApplicationContext().getContentResolver().openInputStream(uri);
699 
700  OutputStream out = new FileOutputStream(file);
701  byte[] buf = new byte[1024];
702  int len;
703  while ((len = in.read(buf)) > 0) {
704  out.write(buf, 0, len);
705  }
706  in.close();
707  out.close();
708  } catch (IOException e) {
709  Log.e(TAG, e.getMessage());
710  }
711  }
712 
713  public String getFileName(Uri uri) {
714  String result = null;
715  if (uri.getScheme().equals("content")) {
716  Cursor cursor = getContentResolver().query(uri, null, null, null, null);
717  try {
718  if (cursor != null && cursor.moveToFirst()) {
719  result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
720  }
721  } finally {
722  cursor.close();
723  }
724  }
725  if (result == null) {
726  result = uri.getPath();
727  int cut = result.lastIndexOf('/');
728  if (cut != -1) {
729  result = result.substring(cut + 1);
730  }
731  }
732  return result;
733  }
734 
735 
736  // Should be called only if read/write permissions are granted!
737  private void postCreate()
738  {
739  Log.i(TAG, "postCreate()");
740 
741  final String[] files = Util.loadFileList(mWorkingDirectory, true);
742  if(files.length == 0)
743  {
744  mButtonLibrary.setVisibility(View.INVISIBLE);
745  }
746  }
747 
749  {
750  Log.i(TAG, String.format("updateCameraDriverSettings() mCameraDriver=%d RTABMapLib.isBuiltWith(%d)=%d", mCameraDriver, mCameraDriver, RTABMapLib.isBuiltWith(nativeApplication, mCameraDriver)?1:0));
751 
752  SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
753  String cameraDriverStr = sharedPref.getString(getString(R.string.pref_key_camera_driver), getString(R.string.pref_default_camera_driver));
754  mCameraDriver = Integer.parseInt(cameraDriverStr);
755 
756  if(mCameraDriver == -1)
757  {
758  // Prioritize tango if available
759  mCameraDriver = 0;
760  SharedPreferences.Editor editor = sharedPref.edit();
761  editor.putString(getString(R.string.pref_key_camera_driver), "0");
762  editor.commit();
763  }
764 
765  if(mCameraDriver == 0 && (!CheckTangoCoreVersion(MIN_TANGO_CORE_VERSION) || !RTABMapLib.isBuiltWith(nativeApplication, 0)))
766  {
767  if(mIsAREngineAvailable && RTABMapLib.isBuiltWith(nativeApplication, 2))
768  {
769  SharedPreferences.Editor editor = sharedPref.edit();
770  editor.putString(getString(R.string.pref_key_camera_driver), "2");
771  editor.commit();
772  }
773  else if(mIsARCoreAvailable)
774  {
775  SharedPreferences.Editor editor = sharedPref.edit();
776  editor.putString(getString(R.string.pref_key_camera_driver), "3");
777  editor.commit();
778  }
779  }
780  else if(((mCameraDriver == 1 && (!RTABMapLib.isBuiltWith(nativeApplication, 0) || !mIsARCoreAvailable)) ||
781  (mCameraDriver == 3 && !mIsARCoreAvailable)))
782  {
783  if(CheckTangoCoreVersion(MIN_TANGO_CORE_VERSION) && RTABMapLib.isBuiltWith(nativeApplication, 0))
784  {
785  SharedPreferences.Editor editor = sharedPref.edit();
786  editor.putString(getString(R.string.pref_key_camera_driver), "0");
787  editor.commit();
788  }
789  else if(mIsAREngineAvailable && RTABMapLib.isBuiltWith(nativeApplication, 2))
790  {
791  SharedPreferences.Editor editor = sharedPref.edit();
792  editor.putString(getString(R.string.pref_key_camera_driver), "2");
793  editor.commit();
794  }
795  }
796  else if(mCameraDriver == 2 && (!mIsAREngineAvailable || !RTABMapLib.isBuiltWith(nativeApplication, 2)))
797  {
798  if(CheckTangoCoreVersion(MIN_TANGO_CORE_VERSION) && RTABMapLib.isBuiltWith(nativeApplication, 0))
799  {
800  SharedPreferences.Editor editor = sharedPref.edit();
801  editor.putString(getString(R.string.pref_key_camera_driver), "0");
802  editor.commit();
803  }
804  else if(mIsARCoreAvailable)
805  {
806  SharedPreferences.Editor editor = sharedPref.edit();
807  editor.putString(getString(R.string.pref_key_camera_driver), "3");
808  editor.commit();
809  }
810  }
811  }
812 
813  private void isArCoreAvailable() {
814  ArCoreApk.Availability availability = ArCoreApk.getInstance().checkAvailability(this);
815  if (availability.isTransient()) {
816  // Re-query at 5Hz while compatibility is checked in the background.
817  new Handler().postDelayed(new Runnable() {
818  @Override
819  public void run() {
820  isArCoreAvailable();
821  }
822  }, 200);
823  }
824  if (availability.isSupported()) {
825  Log.i(TAG, "ARCore supported");
826  mIsARCoreAvailable = true;
827  updateCameraDriverSettings();
828  } else { // Unsupported or unknown.
829  Log.i(TAG, "ARCore supported");
830  mIsARCoreAvailable = false;
831  updateCameraDriverSettings();
832  }
833  }
834 
835  private void isArEngineAvailable() {
836  try {
837  AREnginesApk.ARAvailability availability = AREnginesApk.checkAvailability(this);
838  if (availability.isTransient()) {
839  // Re-query at 5Hz while compatibility is checked in the background.
840  new Handler().postDelayed(new Runnable() {
841  @Override
842  public void run() {
843  isArEngineAvailable();
844  }
845  }, 200);
846  }
847  if (availability.isSupported()) {
848  Log.i(TAG, "AREngine supported");
849  mIsAREngineAvailable = true;
850  updateCameraDriverSettings();
851  } else { // Unsupported or unknown.
852  Log.i(TAG, "AREngine not supported");
853  mIsAREngineAvailable = false;
854  updateCameraDriverSettings();
855  }
856  }
857  catch(UnsatisfiedLinkError e)
858  {
859  Log.i(TAG, "AREngine not supported");
860  mIsAREngineAvailable = false;
861  }
862  }
863 
864 
865  @Override
866  public void onDestroy() {
867  super.onDestroy();
868 
869  if(!DISABLE_LOG) Log.d(TAG, "onDestroy()");
870  // Synchronized to avoid racing onDrawFrame.
871  synchronized (this) {
872  RTABMapLib.destroyNativeApplication(nativeApplication);
873  nativeApplication = 0;
874  }
875  }
876 
877  @Override
878  public void onSensorChanged(SensorEvent event) {
879  if(event.sensor == mAccelerometer || event.sensor == mMagnetometer)
880  {
881  if (event.sensor == mAccelerometer) {
882  System.arraycopy(event.values, 0, mLastAccelerometer, 0, event.values.length);
883  mLastAccelerometerSet = true;
884  } else if (event.sensor == mMagnetometer) {
885  System.arraycopy(event.values, 0, mLastMagnetometer, 0, event.values.length);
886  mLastMagnetometerSet = true;
887  }
888  if (mLastAccelerometerSet && mLastMagnetometerSet) {
889  SensorManager.getRotationMatrix(mR, null, mLastAccelerometer, mLastMagnetometer);
890  mRMat.setValues(mR);
891  mNewR.setConcat(mRMat, mDeviceToCamera) ;
892  mNewR.getValues(mR);
893  SensorManager.getOrientation(mR, mOrientation);
894  mCompassDeg = mOrientation[0] * 180.0f/(float)Math.PI;
895  if(mCompassDeg<0.0f)
896  {
897  mCompassDeg += 360.0f;
898  }
899  }
900  }
901  else if(event.sensor == mAmbientTemperature)
902  {
903  mLastEnvSensors[1] = event.values[0];
904  mLastEnvSensorsSet[1] = true;
905  RTABMapLib.addEnvSensor(nativeApplication, 2, event.values[0]);
906  }
907  else if(event.sensor == mAmbientAirPressure)
908  {
909  mLastEnvSensors[2] = event.values[0];
910  mLastEnvSensorsSet[2] = true;
911  RTABMapLib.addEnvSensor(nativeApplication, 3, event.values[0]);
912  }
913  else if(event.sensor == mAmbientLight)
914  {
915  mLastEnvSensors[3] = event.values[0];
916  mLastEnvSensorsSet[3] = true;
917  RTABMapLib.addEnvSensor(nativeApplication, 4, event.values[0]);
918  }
919  else if(event.sensor == mAmbientRelativeHumidity)
920  {
921  mLastEnvSensors[4] = event.values[0];
922  mLastEnvSensorsSet[4] = true;
923  RTABMapLib.addEnvSensor(nativeApplication, 5, event.values[0]);
924  }
925  }
926 
927  @Override
928  public void onAccuracyChanged(Sensor sensor, int accuracy) {
929  // not in use
930  }
931 
932 
933  public int getStatusBarHeight() {
934  int result = 0;
935  int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
936  if (resourceId > 0) {
937  result = getResources().getDimensionPixelSize(resourceId);
938  }
939  return result;
940  }
941  public int getActionBarHeight() {
942  int result = 0;
943  TypedValue tv = new TypedValue();
944  if (getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true))
945  {
946  result = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
947  }
948 
949  return result;
950  }
951 
952  @Override
953  public void onWindowFocusChanged(boolean hasFocus) {
954 
955  super.onWindowFocusChanged(hasFocus);
956 
957  if(!mHudVisible)
958  {
959  mRenderer.setOffset(!hasFocus?-mStatusBarHeight:0);
960  }
961  }
962 
963  // This snippet hides the system bars.
964  private void setNavVisibility(boolean visible) {
965  int newVis = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
966  | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
967  | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
968  if (!visible) {
969  newVis |= View.SYSTEM_UI_FLAG_LOW_PROFILE
970  | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
971  | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
972  | View.SYSTEM_UI_FLAG_IMMERSIVE;
973  mRenderer.setOffset(!hasWindowFocus()?-mStatusBarHeight:0);
974  }
975  else
976  {
977  mRenderer.setOffset(-mStatusBarHeight-mActionBarHeight);
978  }
979 
980  // Set the new desired visibility.
981  mDecorView.setSystemUiVisibility(newVis);
982  }
983 
984  @Override
985  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
986  // Check which request we're responding to
987  if (requestCode == Tango.TANGO_INTENT_ACTIVITYCODE) {
988  // Make sure the request was successful
989  if (resultCode == RESULT_CANCELED) {
990  mToast.makeText(this, "Motion Tracking Permissions Required!", mToast.LENGTH_SHORT).show();
991  }
992  }
993  else if (requestCode == SKETCHFAB_ACTIVITY_CODE) {
994  // Make sure the request was successful
995  if (resultCode == RESULT_OK) {
996  mAuthToken = data.getStringExtra(RTABMAP_AUTH_TOKEN_KEY);
997  }
998  }
999  }
1000 
1001  @Override
1002  public boolean onMenuOpened(int featureId, Menu menu) {
1003  mMenuOpened = true;
1004  return super.onMenuOpened(featureId, menu);
1005  }
1006 
1007  @Override
1008  public void onPanelClosed(int featureId, Menu menu) {
1009  mMenuOpened = false;
1010  }
1011 
1012  @Override
1013  public void onBackPressed() {
1014 
1015  Date t = new Date();
1016  boolean doubleBack = t.getTime() - mBackClickedTime.getTime() < 3500; // mToast.LENGTH_LONG
1017  mBackClickedTime = t;
1018  if(mState == State.STATE_MAPPING)
1019  {
1020  stopMapping();
1021  }
1022  else if(mState == State.STATE_CAMERA || mState == State.STATE_VISUALIZING_CAMERA)
1023  {
1024  stopCamera();
1025  }
1026  else if(mState == State.STATE_IDLE || mState == State.STATE_WELCOME)
1027  {
1028  if(doubleBack)
1029  {
1030  super.onBackPressed();
1031  }
1032  else
1033  {
1034  mToast.makeText(this, "Press Back once more to exit", mToast.LENGTH_LONG).show();
1035  }
1036  }
1037  else if(mState == State.STATE_VISUALIZING)
1038  {
1039  closeVisualization();
1040  RTABMapLib.postExportation(nativeApplication, false);
1041  }
1042  }
1043 
1044  @Override
1045  protected void onPause() {
1046  super.onPause();
1047  mGLView.onPause();
1048  stopDisconnectTimer();
1049 
1050  if(!DISABLE_LOG) Log.i(TAG, "onPause()");
1051  mOnPause = true;
1052 
1053  if(mState == State.STATE_VISUALIZING_CAMERA)
1054  {
1055  stopCamera();
1056  }
1057  else if(mState == State.STATE_MAPPING || mState == State.STATE_CAMERA)
1058  {
1059  stopMapping();
1060  }
1061 
1062  mLocationManager.removeUpdates(mLocationListener);
1063  mSensorManager.unregisterListener(this);
1064  mLastAccelerometerSet = false;
1065  mLastMagnetometerSet= false;
1066  mLastEnvSensorsSet[0] = mLastEnvSensorsSet[1]= mLastEnvSensorsSet[2]= mLastEnvSensorsSet[3]= mLastEnvSensorsSet[4]=false;
1067 
1068  // This deletes OpenGL context!
1069  mGLView.onPause();
1070 
1071  mOnPauseStamp = System.currentTimeMillis()/1000;
1072  }
1073 
1074  private void updatePreferences()
1075  {
1076  // update preferences
1077  try
1078  {
1079  Log.i(TAG, "update preferences...");
1080  SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
1081  mUpdateRate = sharedPref.getString(getString(R.string.pref_key_update_rate), getString(R.string.pref_default_update_rate));
1082  String maxSpeed = sharedPref.getString(getString(R.string.pref_key_max_speed), getString(R.string.pref_default_max_speed));
1083  mTimeThr = sharedPref.getString(getString(R.string.pref_key_time_thr), getString(R.string.pref_default_time_thr));
1084  String memThr = sharedPref.getString(getString(R.string.pref_key_mem_thr), getString(R.string.pref_default_mem_thr));
1085  mLoopThr = sharedPref.getString(getString(R.string.pref_key_loop_thr), getString(R.string.pref_default_loop_thr));
1086  String simThr = sharedPref.getString(getString(R.string.pref_key_sim_thr), getString(R.string.pref_default_sim_thr));
1087  mMinInliers = sharedPref.getString(getString(R.string.pref_key_min_inliers), getString(R.string.pref_default_min_inliers));
1088  mMaxOptimizationError = sharedPref.getString(getString(R.string.pref_key_opt_error), getString(R.string.pref_default_opt_error));
1089  float maxOptimizationError = Float.parseFloat(mMaxOptimizationError);
1090  if(maxOptimizationError >0 && maxOptimizationError<1)
1091  {
1092  Log.w(TAG, "Migration of " + getString(R.string.pref_key_opt_error) + " from " + mMaxOptimizationError + " to " + getString(R.string.pref_default_opt_error)) ;
1093  SharedPreferences.Editor editor = sharedPref.edit();
1094  editor.putString(getString(R.string.pref_key_opt_error), getString(R.string.pref_default_opt_error));
1095  editor.commit();
1096  mMaxOptimizationError = getString(R.string.pref_default_opt_error);
1097  }
1098  mMaxFeatures = sharedPref.getString(getString(R.string.pref_key_features_voc), getString(R.string.pref_default_features_voc));
1099  String maxFeaturesLoop = sharedPref.getString(getString(R.string.pref_key_features), getString(R.string.pref_default_features));
1100  String featureType = sharedPref.getString(getString(R.string.pref_key_features_type), getString(R.string.pref_default_features_type));
1101  boolean keepAllDb = sharedPref.getBoolean(getString(R.string.pref_key_keep_all_db), Boolean.parseBoolean(getString(R.string.pref_default_keep_all_db)));
1102  boolean optimizeFromGraphEnd = sharedPref.getBoolean(getString(R.string.pref_key_optimize_end), Boolean.parseBoolean(getString(R.string.pref_default_optimize_end)));
1103  String optimizer = sharedPref.getString(getString(R.string.pref_key_optimizer), getString(R.string.pref_default_optimizer));
1104  String markerDetection = sharedPref.getString(getString(R.string.pref_key_marker_detection), getString(R.string.pref_default_marker_detection));
1105  String markerDetectionDepthError = sharedPref.getString(getString(R.string.pref_key_marker_detection_depth_error), getString(R.string.pref_default_marker_detection_depth_error));
1106  mGPSSaved = PermissionHelper.hasPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) && sharedPref.getBoolean(getString(R.string.pref_key_gps_saved), Boolean.parseBoolean(getString(R.string.pref_default_gps_saved)));
1107  if(mGPSSaved)
1108  {
1109  mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListener);
1110  mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
1111  mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_UI);
1112  }
1113  mEnvSensorsSaved = sharedPref.getBoolean(getString(R.string.pref_key_env_sensors_saved), Boolean.parseBoolean(getString(R.string.pref_default_env_sensors_saved)));
1114  if(mEnvSensorsSaved)
1115  {
1116  mSensorManager.registerListener(this, mAmbientTemperature, SensorManager.SENSOR_DELAY_NORMAL);
1117  mSensorManager.registerListener(this, mAmbientAirPressure, SensorManager.SENSOR_DELAY_NORMAL);
1118  mSensorManager.registerListener(this, mAmbientLight, SensorManager.SENSOR_DELAY_NORMAL);
1119  mSensorManager.registerListener(this, mAmbientRelativeHumidity, SensorManager.SENSOR_DELAY_NORMAL);
1120  mEnvSensorsTimer.schedule(new TimerTask() {
1121 
1122  @Override
1123  public void run() {
1124  WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
1125  int dbm = 0;
1126  if(wifiInfo != null && (dbm = wifiInfo.getRssi()) > -127)
1127  {
1128  mLastEnvSensors[0] = (float)dbm;
1129  mLastEnvSensorsSet[0] = true;
1130  RTABMapLib.addEnvSensor(nativeApplication, 1, mLastEnvSensors[0]);
1131  }
1132  }
1133 
1134  },0,200);
1135  }
1136 
1137  Log.i(TAG, "set mapping parameters");
1138  RTABMapLib.setOnlineBlending(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_blending), Boolean.parseBoolean(getString(R.string.pref_default_blending))));
1139  RTABMapLib.setNodesFiltering(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_nodes_filtering), Boolean.parseBoolean(getString(R.string.pref_default_nodes_filtering))));
1140  RTABMapLib.setRawScanSaved(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_raw_scan_saved), Boolean.parseBoolean(getString(R.string.pref_default_raw_scan_saved))));
1141  RTABMapLib.setFullResolution(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_resolution), Boolean.parseBoolean(getString(R.string.pref_default_resolution))));
1142  RTABMapLib.setSmoothing(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_smoothing), Boolean.parseBoolean(getString(R.string.pref_default_smoothing))));
1143  RTABMapLib.setDepthFromMotion(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_depth_from_motion), Boolean.parseBoolean(getString(R.string.pref_default_depth_from_motion))));
1144  RTABMapLib.setCameraColor(nativeApplication, !sharedPref.getBoolean(getString(R.string.pref_key_fisheye), Boolean.parseBoolean(getString(R.string.pref_default_fisheye))));
1145  RTABMapLib.setAppendMode(nativeApplication, sharedPref.getBoolean(getString(R.string.pref_key_append), Boolean.parseBoolean(getString(R.string.pref_default_append))));
1146  RTABMapLib.setUpstreamRelocalizationAccThr(nativeApplication, Float.parseFloat(sharedPref.getString(getString(R.string.pref_key_arcore_relocalization_acc_thr), getString(R.string.pref_default_arcore_relocalization_acc_thr))));
1147  RTABMapLib.setMappingParameter(nativeApplication, "Rtabmap/DetectionRate", mUpdateRate);
1148  RTABMapLib.setMappingParameter(nativeApplication, "Rtabmap/TimeThr", mTimeThr);
1149  RTABMapLib.setMappingParameter(nativeApplication, "Rtabmap/MemoryThr", memThr);
1150  RTABMapLib.setMappingParameter(nativeApplication, "RGBD/LinearSpeedUpdate", maxSpeed);
1151  RTABMapLib.setMappingParameter(nativeApplication, "RGBD/AngularSpeedUpdate", String.valueOf(Float.parseFloat(maxSpeed)/2.0f));
1152  RTABMapLib.setMappingParameter(nativeApplication, "Mem/RehearsalSimilarity", simThr);
1153  RTABMapLib.setMappingParameter(nativeApplication, "Kp/MaxFeatures", mMaxFeatures);
1154  RTABMapLib.setMappingParameter(nativeApplication, "Vis/MaxFeatures", maxFeaturesLoop);
1155  RTABMapLib.setMappingParameter(nativeApplication, "Vis/MinInliers", mMinInliers);
1156  RTABMapLib.setMappingParameter(nativeApplication, "Rtabmap/LoopThr", mLoopThr);
1157  RTABMapLib.setMappingParameter(nativeApplication, "RGBD/OptimizeMaxError", mMaxOptimizationError);
1158  RTABMapLib.setMappingParameter(nativeApplication, "Kp/DetectorStrategy", featureType);
1159  RTABMapLib.setMappingParameter(nativeApplication, "Vis/FeatureType", featureType);
1160  RTABMapLib.setMappingParameter(nativeApplication, "Mem/NotLinkedNodesKept", String.valueOf(keepAllDb));
1161  RTABMapLib.setMappingParameter(nativeApplication, "RGBD/OptimizeFromGraphEnd", String.valueOf(optimizeFromGraphEnd));
1162  RTABMapLib.setMappingParameter(nativeApplication, "Optimizer/Strategy", optimizer);
1163  if(Integer.parseInt(markerDetection) == -1)
1164  {
1165  RTABMapLib.setMappingParameter(nativeApplication, "RGBD/MarkerDetection", "false");
1166  }
1167  else
1168  {
1169  RTABMapLib.setMappingParameter(nativeApplication, "RGBD/MarkerDetection", "true");
1170  RTABMapLib.setMappingParameter(nativeApplication, "Marker/Dictionary", markerDetection);
1171  RTABMapLib.setMappingParameter(nativeApplication, "Marker/CornerRefinementMethod", Integer.parseInt(markerDetection) > 16?"3":"0");
1172  }
1173  RTABMapLib.setMappingParameter(nativeApplication, "Marker/MaxDepthError", markerDetectionDepthError);
1174 
1175  Log.i(TAG, "set exporting parameters...");
1176  RTABMapLib.setCloudDensityLevel(nativeApplication, Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_density), getString(R.string.pref_default_density))));
1177  RTABMapLib.setMaxCloudDepth(nativeApplication, Float.parseFloat(sharedPref.getString(getString(R.string.pref_key_depth), getString(R.string.pref_default_depth))));
1178  RTABMapLib.setMinCloudDepth(nativeApplication, Float.parseFloat(sharedPref.getString(getString(R.string.pref_key_min_depth), getString(R.string.pref_default_min_depth))));
1179  RTABMapLib.setPointSize(nativeApplication, Float.parseFloat(sharedPref.getString(getString(R.string.pref_key_point_size), getString(R.string.pref_default_point_size))));
1180  RTABMapLib.setMeshAngleTolerance(nativeApplication, Float.parseFloat(sharedPref.getString(getString(R.string.pref_key_angle), getString(R.string.pref_default_angle))));
1181  RTABMapLib.setMeshTriangleSize(nativeApplication, Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_triangle), getString(R.string.pref_default_triangle))));
1182  float bgColor = Float.parseFloat(sharedPref.getString(getString(R.string.pref_key_background_color), getString(R.string.pref_default_background_color)));
1183  RTABMapLib.setBackgroundColor(nativeApplication, bgColor);
1184  mRenderer.setTextColor(bgColor>=0.6f?0.0f:1.0f);
1185 
1186  Log.i(TAG, "set rendering parameters...");
1187  RTABMapLib.setClusterRatio(nativeApplication, Float.parseFloat(sharedPref.getString(getString(R.string.pref_key_cluster_ratio), getString(R.string.pref_default_cluster_ratio))));
1188  RTABMapLib.setMaxGainRadius(nativeApplication, Float.parseFloat(sharedPref.getString(getString(R.string.pref_key_gain_max_radius), getString(R.string.pref_default_gain_max_radius))));
1189  RTABMapLib.setRenderingTextureDecimation(nativeApplication, Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_rendering_texture_decimation), getString(R.string.pref_default_rendering_texture_decimation))));
1190 
1191  if(mItemRenderingPointCloud != null)
1192  {
1193  int renderingType = sharedPref.getInt(getString(R.string.pref_key_rendering), Integer.parseInt(getString(R.string.pref_default_rendering)));
1194  if(renderingType == 0)
1195  {
1196  mItemRenderingPointCloud.setChecked(true);
1197  }
1198  else if(renderingType == 1)
1199  {
1200  mItemRenderingMesh.setChecked(true);
1201  }
1202  else
1203  {
1204  mItemRenderingTextureMesh.setChecked(true);
1205  }
1207  nativeApplication,
1208  mItemRenderingMesh.isChecked() || mItemRenderingTextureMesh.isChecked(),
1209  mItemRenderingTextureMesh.isChecked());
1210 
1211  mButtonBackfaceShown.setVisibility(mItemRenderingMesh.isChecked() || mItemRenderingTextureMesh.isChecked()?View.VISIBLE:View.INVISIBLE);
1212  }
1213  }
1214  catch(Exception e)
1215  {
1216  Log.e(TAG, "Error parsing preferences: " + e.getMessage());
1217  mToast.makeText(this, String.format("Error parsing preferences: "+e.getMessage()), mToast.LENGTH_LONG).show();
1218  }
1219  }
1220 
1221  @Override
1222  protected void onResume() {
1223  super.onResume();
1224 
1225  setAndroidOrientation();
1226 
1227  updateCameraDriverSettings();
1228  updatePreferences();
1229 
1230  if(mState == State.STATE_MAPPING || mState == State.STATE_CAMERA)
1231  {
1232  String message = new String();
1233  if(mOnPause)
1234  {
1235  if(System.currentTimeMillis()/1000 - mOnPauseStamp < 1)
1236  {
1237  message = String.format("RTAB-Map has been interrupted by another application, Camera should be re-initialized! Set your phone/tablet in Airplane mode if this happens often.");
1238  }
1239  else
1240  {
1241  message = String.format("Hold Tight! Initializing Camera Service...");
1242  }
1243  mToast.makeText(this, "Mapping is paused!", mToast.LENGTH_LONG).show();
1244  }
1245  else
1246  {
1247  message = String.format("Hold Tight! Initializing Camera Service...\nTip: If the camera is still drifting just after the mapping has started, do \"Reset\".");
1248  }
1249  startCamera(message);
1250  }
1251  mOnPause = false;
1252 
1253  if(!DISABLE_LOG) Log.i(TAG, String.format("onResume()"));
1254  mGLView.onResume();
1255  }
1256 
1257  @Override
1258  public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] results) {
1259 
1260  switch (requestCode) {
1262  // If request is cancelled, the result arrays are empty.
1263  if (results.length > 0 && results[0] == PackageManager.PERMISSION_GRANTED) {
1264  // permission was granted, yay! Do the
1265  // contacts-related task you need to do.
1266  postCreate();
1267  } else {
1268  // permission denied, boo! Disable the
1269  // functionality that depends on this permission.
1270  Toast.makeText(this, "Storage read/write permissions are needed to run this application", Toast.LENGTH_LONG).show();
1271  if (!PermissionHelper.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
1272  PermissionHelper.launchPermissionSettings(this); // Permission denied with checking "Do not ask again".
1273  }
1274  finish();
1275  }
1276  return;
1277  }
1279  if (results.length > 0 && results[0] == PackageManager.PERMISSION_GRANTED) {
1280  // permission was granted, yay!
1281  startCamera(String.format("Hold Tight! Initializing Camera Service...\n"
1282  + "Tip: If the camera is still drifting just after the mapping has started, do \"Reset\"."));
1283  } else {
1284  Toast.makeText(this, "Camera permission is needed for scanning and motion tracking.", Toast.LENGTH_LONG).show();
1285  if (!PermissionHelper.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
1286  PermissionHelper.launchPermissionSettings(this); // Permission denied with checking "Do not ask again".
1287  }
1288  }
1289  return;
1290  }
1292  if (results.length > 0 && results[0] == PackageManager.PERMISSION_GRANTED) {
1293  // permission was granted, yay!
1294  } else {
1295  Toast.makeText(this, "Internet permission is needed to share scans.", Toast.LENGTH_LONG).show();
1296  if (!PermissionHelper.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
1297  PermissionHelper.launchPermissionSettings(this); // Permission denied with checking "Do not ask again".
1298  }
1299  }
1300  return;
1301  }
1302  }
1303  }
1304 
1305  private void startCamera(final String message)
1306  {
1307  // If we did not yet obtain runtime permission on Android M and above,
1308  // now is a good time to ask the user for it.
1309  if (!PermissionHelper.hasPermission(this, Manifest.permission.CAMERA)) {
1310  PermissionHelper.requestPermission(this, Manifest.permission.CAMERA);
1311  return;
1312  }
1313 
1314  SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
1315  String cameraDriverStr = sharedPref.getString(getString(R.string.pref_key_camera_driver), getString(R.string.pref_default_camera_driver));
1316  final boolean depthFromMotion = sharedPref.getBoolean(getString(R.string.pref_key_depth_from_motion), Boolean.parseBoolean(getString(R.string.pref_default_depth_from_motion)));
1317  mCameraDriver = Integer.parseInt(cameraDriverStr);
1318 
1319  Log.i(TAG, String.format("startCamera() driver=%d", mCameraDriver));
1320  if(mCameraDriver == 0) // Tango
1321  {
1322  // Check if the Tango Core is out dated.
1323  if (!CheckTangoCoreVersion(MIN_TANGO_CORE_VERSION)) {
1324  mToast.makeText(this, "Current camera driver selected is Tango, but Tango is not available or outdated on this phone. Abort scanning...", mToast.LENGTH_LONG).show();
1325  return;
1326  }
1327 
1328  if (!Tango.hasPermission(this, Tango.PERMISSIONTYPE_MOTION_TRACKING)) {
1329  if(!DISABLE_LOG) Log.i(TAG, String.format("Asking for motion tracking permission"));
1330  startActivityForResult(
1331  Tango.getRequestPermissionIntent(Tango.PERMISSIONTYPE_MOTION_TRACKING),
1332  Tango.TANGO_INTENT_ACTIVITYCODE);
1333  return;
1334  }
1335  else
1336  {
1337  mCameraServiceConnectionUsed = TangoInitializationHelper.bindTangoService(getActivity(), mCameraServiceConnection);
1338  if(mCameraServiceConnectionUsed)
1339  {
1340  mProgressDialog.setTitle("");
1341  mProgressDialog.setMessage(message);
1342  mProgressDialog.show();
1343  resetNoTouchTimer(true);
1344 
1345  // When the service has been connected, RTABMapLib.onCameraServiceConnected(service) should be called, see above
1346  }
1347  else
1348  {
1349  mToast.makeText(this, "Current camera driver selected is Tango, but Tango service binding failed. Abort scanning...", mToast.LENGTH_LONG).show();
1350  }
1351  }
1352  }
1353  else if(mCameraDriver == 1 || mCameraDriver == 2 || mCameraDriver == 3)
1354  {
1355  if((mCameraDriver == 1 || mCameraDriver == 3) && !mIsARCoreAvailable)
1356  {
1357  mToast.makeText(this, "ARCore not supported on this phone! Cannot start a new scan.", mToast.LENGTH_LONG).show();
1358  return;
1359  }
1360  if(mCameraDriver == 2 && !mIsAREngineAvailable)
1361  {
1362  mToast.makeText(this, "AREngine not supported on this phone! Cannot start a new scan.", mToast.LENGTH_LONG).show();
1363  return;
1364  }
1365 
1366  // only point cloud supported
1367  if(mCameraDriver==1 && !mItemRenderingPointCloud.isChecked())
1368  {
1369  mItemRenderingPointCloud.setChecked(true);
1370  }
1371  Thread bindThread = new Thread(new Runnable() {
1372  public void run() {
1373 
1374  if(mCameraDriver==1 && !depthFromMotion)
1375  {
1377  nativeApplication,
1378  mItemRenderingMesh.isChecked() || mItemRenderingTextureMesh.isChecked(),
1379  mItemRenderingTextureMesh.isChecked());
1380  }
1381  final boolean cameraStartSucess = RTABMapLib.startCamera(nativeApplication, null, getApplicationContext(), getActivity(), mCameraDriver);
1382  runOnUiThread(new Runnable() {
1383  public void run() {
1384  boolean localSuccess = cameraStartSucess;
1385  if(cameraStartSucess && mCameraDriver == 3)
1386  {
1387  synchronized (this) {
1388  mArCoreCamera = new ARCoreSharedCamera(getActivity());
1389  mArCoreCamera.setToast(mToast);
1390  mProgressDialog.setTitle("");
1391  mProgressDialog.setMessage(message);
1392  mProgressDialog.show();
1393  if(!mArCoreCamera.openCamera())
1394  {
1395  mToast.makeText(getActivity(), "Current camera driver selected is ARCore Java, but initialization failed. Abort scanning...", mToast.LENGTH_LONG).show();
1396  mArCoreCamera = null;
1397  localSuccess = false;
1398  }
1399  else
1400  {
1401  mRenderer.setCamera(mArCoreCamera);
1402  if((mState==State.STATE_IDLE || mState==State.STATE_WELCOME) && !mArCoreCamera.isDepthSupported())
1403  {
1404  mItemRenderingPointCloud.setChecked(true);
1405  RTABMapLib.setMeshRendering(nativeApplication, false, false);
1406  mToast.makeText(getApplicationContext(), "Depth camera not found, only poses and RGB images can be recorded.", mToast.LENGTH_LONG).show();
1407  }
1408  }
1409  }
1410  }
1411 
1412  mProgressDialog.dismiss();
1413  if(!localSuccess)
1414  {
1415  mToast.makeText(getApplicationContext(),
1416  String.format("Failed to intialize Camera!"), mToast.LENGTH_LONG).show();
1417  }
1418  else
1419  {
1420  if((mState==State.STATE_IDLE || mState==State.STATE_WELCOME) && mCameraDriver == 1 && !depthFromMotion)
1421  {
1422  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();
1423  }
1425  if(mState==State.STATE_VISUALIZING_CAMERA && mItemLocalizationMode.isChecked())
1426  {
1427  RTABMapLib.setPausedMapping(nativeApplication, false);
1428  }
1429  }
1430  }
1431  });
1432  }
1433  });
1434  bindThread.start();
1435  }
1436  else
1437  {
1438  mToast.makeText(this, "Supported camera driver not found! Cannot start a new scan.", mToast.LENGTH_LONG).show();
1439  }
1440  }
1441 
1442  private void setCamera(int type)
1443  {
1444  if(!DISABLE_LOG) Log.i(TAG, String.format("called setCamera(type=%d);", type));
1445 
1446  // for convenience, for a refresh of the memory used
1447  long freeMemory = getFreeMemory();
1448  mStatusTexts[1] = getString(R.string.memory)+String.valueOf(mFreeMemoryOnStart>freeMemory?mFreeMemoryOnStart-freeMemory:0);
1449  mStatusTexts[2] = getString(R.string.free_memory)+String.valueOf(freeMemory);
1450  updateStatusTexts();
1451 
1452  RTABMapLib.setCamera(nativeApplication, type);
1453  mButtonCameraView.setSelection(type, true);
1454  mSeekBarOrthoCut.setVisibility(type!=3?View.INVISIBLE:View.VISIBLE);
1455  mSeekBarGrid.setVisibility(mSeekBarGrid.isEnabled() && type==3?View.VISIBLE:View.INVISIBLE);
1456  if(type==3)
1457  {
1458  mSeekBarOrthoCut.setMax(120);
1459  mSeekBarOrthoCut.setProgress(80);
1460  }
1461  }
1462 
1463  @Override
1464  public void onClick(View v) {
1465  // Handle button clicks.
1466  switch (v.getId()) {
1467  case R.id.gl_surface_view:
1468  break;
1469  case R.id.start_button:
1470  startMapping();
1471  break;
1472  case R.id.stop_button:
1473  if(mState == State.STATE_VISUALIZING_CAMERA)
1474  {
1475  stopCamera();
1476  }
1477  else
1478  {
1479  stopMapping();
1480  }
1481  break;
1482  case R.id.light_button:
1483  RTABMapLib.setLighting(nativeApplication, mButtonLighting.isChecked());
1484  break;
1485  case R.id.backface_button:
1486  RTABMapLib.setBackfaceCulling(nativeApplication, !mButtonBackfaceShown.isChecked());
1487  break;
1488  case R.id.wireframe_button:
1489  RTABMapLib.setWireframe(nativeApplication, mButtonWireframe.isChecked());
1490  break;
1491  case R.id.close_visualization_button:
1492  closeVisualization();
1493  RTABMapLib.postExportation(nativeApplication, false);
1494  break;
1495  case R.id.button_saveOnDevice:
1496  saveOnDevice();
1497  break;
1498  case R.id.button_shareToSketchfab:
1499  shareToSketchfab();
1500  break;
1501  case R.id.button_library:
1502  openDatabase();
1503  break;
1504  case R.id.button_new_scan:
1505  newScan();
1506  break;
1507  default:
1508  return;
1509  }
1510  resetNoTouchTimer();
1511  }
1512 
1513  private void closeVisualization()
1514  {
1515  if(mSavedRenderingType==0)
1516  {
1517  mItemRenderingPointCloud.setChecked(true);
1518  }
1519  else if(mSavedRenderingType==1)
1520  {
1521  mItemRenderingMesh.setChecked(true);
1522  }
1523  else
1524  {
1525  mItemRenderingTextureMesh.setChecked(true);
1526  }
1527  updateState(State.STATE_IDLE);
1528  }
1529 
1530  public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
1531  setCamera(pos);
1532  resetNoTouchTimer();
1533  }
1534 
1535  public void onNothingSelected(AdapterView<?> parent) {
1536  resetNoTouchTimer();
1537  }
1538 
1539  private void setAndroidOrientation() {
1540  Display display = getWindowManager().getDefaultDisplay();
1541  Camera.CameraInfo colorCameraInfo = new Camera.CameraInfo();
1542  SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
1543  boolean fisheye = sharedPref.getBoolean(getString(R.string.pref_key_fisheye), Boolean.parseBoolean(getString(R.string.pref_default_fisheye)));
1544  Camera.getCameraInfo(fisheye?1:0, colorCameraInfo);
1545  RTABMapLib.setScreenRotation(nativeApplication, display.getRotation(), colorCameraInfo.orientation);
1546  }
1547 
1548  class DoubleTapGestureDetector extends GestureDetector.SimpleOnGestureListener {
1549 
1550  @Override
1551  public boolean onDoubleTap(MotionEvent event) {
1552  if(!DISABLE_LOG) Log.i(TAG, "onDoubleTap");
1553  float normalizedX = event.getX(0) / mScreenSize.x;
1554  float normalizedY = event.getY(0) / mScreenSize.y;
1555  RTABMapLib.onTouchEvent(nativeApplication, 3, event.getActionMasked(), normalizedX, normalizedY, 0.0f, 0.0f);
1556  return true;
1557  }
1558  @Override
1559  public boolean onSingleTapConfirmed(MotionEvent event) {
1560  if(!DISABLE_LOG) Log.i(TAG, "onSingleTapConfirmed");
1561  if(mHudVisible)
1562  {
1563  notouchHandler.removeCallbacks(notouchCallback);
1564  notouchHandler.postDelayed(notouchCallback, 0);
1565  }
1566  else
1567  {
1568  resetNoTouchTimer(true);
1569  }
1570  return true;
1571  }
1572  }
1573 
1574  @Override
1575  public boolean onCreateOptionsMenu(Menu menu) {
1576  if(!DISABLE_LOG) Log.i(TAG, "called onCreateOptionsMenu;");
1577 
1578  MenuInflater inflater = getMenuInflater();
1579  inflater.inflate(R.menu.optionmenu, menu);
1580 
1581  getActionBar().setDisplayShowHomeEnabled(true);
1582  getActionBar().setIcon(R.drawable.ic_launcher);
1583 
1584  mItemSave = menu.findItem(R.id.save);
1585  mItemOpen = menu.findItem(R.id.open);
1586  mItemNewScan = menu.findItem(R.id.new_scan);
1587  mItemPostProcessing = menu.findItem(R.id.post_processing);
1588  mItemExport = menu.findItem(R.id.export);
1589  mItemSettings = menu.findItem(R.id.settings);
1590  mItemModes = menu.findItem(R.id.modes);
1591  mItemResume = menu.findItem(R.id.resume);
1592  mItemLocalizationMode = menu.findItem(R.id.localization_mode);
1593  mItemTrajectoryMode = menu.findItem(R.id.trajectory_mode);
1594  mItemRenderingPointCloud = menu.findItem(R.id.point_cloud);
1595  mItemRenderingMesh = menu.findItem(R.id.mesh);
1596  mItemRenderingTextureMesh = menu.findItem(R.id.texture_mesh);
1597  mItemDataRecorderMode = menu.findItem(R.id.data_recorder);
1598  mItemStatusVisibility = menu.findItem(R.id.status);
1599  mItemDebugVisibility = menu.findItem(R.id.debug);
1600  mItemSave.setEnabled(false);
1601  mItemNewScan.setEnabled(true);
1602  mItemExport.setEnabled(false);
1603  mItemOpen.setEnabled(true);
1604  mItemPostProcessing.setEnabled(false);
1605  mItemDataRecorderMode.setEnabled(false);
1606 
1607  try
1608  {
1609  SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
1610  int renderingType = sharedPref.getInt(getString(R.string.pref_key_rendering), Integer.parseInt(getString(R.string.pref_default_rendering)));
1611  if(renderingType == 0)
1612  {
1613  mItemRenderingPointCloud.setChecked(true);
1614  }
1615  else if(renderingType == 1)
1616  {
1617  mItemRenderingMesh.setChecked(true);
1618  }
1619  else
1620  {
1621  mItemRenderingTextureMesh.setChecked(true);
1622  }
1624  nativeApplication,
1625  mItemRenderingMesh.isChecked() || mItemRenderingTextureMesh.isChecked(),
1626  mItemRenderingTextureMesh.isChecked());
1627 
1628  if(mButtonBackfaceShown != null)
1629  {
1630  mButtonBackfaceShown.setVisibility(mItemRenderingMesh.isChecked() || mItemRenderingTextureMesh.isChecked()?View.VISIBLE:View.INVISIBLE);
1631  }
1632  }
1633  catch(Exception e)
1634  {
1635  Log.e(TAG, "Error parsing rendering preferences: " + e.getMessage());
1636  mToast.makeText(this, String.format("Error parsing rendering preferences: "+e.getMessage()), mToast.LENGTH_LONG).show();
1637  }
1638 
1639  updateState(mState);
1640 
1641  return true;
1642  }
1643 
1644  private long getFreeMemory()
1645  {
1646  MemoryInfo mi = new MemoryInfo();
1647  ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
1648  activityManager.getMemoryInfo(mi);
1649  return mi.availMem / 0x100000L; // MB
1650  }
1651 
1652  private void updateStatusTexts()
1653  {
1654  if(mItemStatusVisibility != null && mItemDebugVisibility != null)
1655  {
1656  if(mState == State.STATE_WELCOME)
1657  {
1658  mRenderer.updateTexts(null);
1659  }
1660  else if((mItemStatusVisibility.isChecked() || mState == State.STATE_VISUALIZING_WHILE_LOADING) && mItemDebugVisibility.isChecked())
1661  {
1662  mRenderer.updateTexts(mStatusTexts);
1663  }
1664  else if((mItemStatusVisibility.isChecked() || mState == State.STATE_VISUALIZING_WHILE_LOADING))
1665  {
1666  mRenderer.updateTexts(Arrays.copyOfRange(mStatusTexts, 0, STATUS_TEXTS_POSE_INDEX-1));
1667  }
1668  else if(mItemDebugVisibility.isChecked())
1669  {
1670  mRenderer.updateTexts(Arrays.copyOfRange(mStatusTexts, STATUS_TEXTS_POSE_INDEX-1, mStatusTexts.length));
1671  }
1672  else
1673  {
1674  mRenderer.updateTexts(null);
1675  }
1676  }
1677  if(mGLView.getRenderMode() == GLSurfaceView.RENDERMODE_WHEN_DIRTY)
1678  {
1679  mGLView.requestRender();
1680  }
1681  }
1682 
1683  private void updateStatsUI(
1684  int loopClosureId,
1685  int inliers,
1686  int matches,
1687  int rejected,
1688  float optimizationMaxError,
1689  float optimizationMaxErrorRatio,
1690  boolean fastMovement,
1691  int landmarkDetected,
1692  String[] statusTexts)
1693  {
1694  for(int i = 1; i<mStatusTexts.length && i<statusTexts.length; ++i)
1695  {
1696  mStatusTexts[i] = statusTexts[i];
1697  }
1698  if(mState == State.STATE_MAPPING)
1699  {
1700  String updateValue = mUpdateRate.compareTo("0")==0?"Max":mUpdateRate;
1701  mStatusTexts[0] = getString(R.string.status)+(mItemDataRecorderMode!=null&&mItemDataRecorderMode.isChecked()?String.format("Recording (%s Hz)", updateValue):mItemLocalizationMode!=null && mItemLocalizationMode.isChecked()?String.format("Localization (%s Hz)", updateValue):String.format("Mapping (%s Hz)", updateValue));
1702  }
1703 
1704  updateStatusTexts();
1705 
1706  if(mButtonStart!=null && mState == State.STATE_MAPPING)
1707  {
1708  if(mButtonStart.getVisibility() != View.VISIBLE)
1709  {
1710  //check if we are low in memory
1711  long memoryFree = getFreeMemory();
1712  long memoryUsed = mFreeMemoryOnStart>memoryFree?mFreeMemoryOnStart-memoryFree:0;
1713 
1714  if(memoryFree < 400)
1715  {
1716  stopMapping();
1717 
1718  if(mMemoryWarningDialog!=null)
1719  {
1720  mMemoryWarningDialog.dismiss();
1721  mMemoryWarningDialog = null;
1722  }
1723 
1724  mMemoryWarningDialog = new AlertDialog.Builder(getActivity())
1725  .setTitle("Memory is full!")
1726  .setCancelable(false)
1727  .setMessage(String.format("Scanning has been paused because free memory is too "
1728  + "low (%d MB). You should be able to save the database but some post-processing and exporting options may fail. "
1729  + "\n\nNote that for large environments, you can save multiple databases and "
1730  + "merge them with RTAB-Map Desktop version.", memoryUsed))
1731  .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
1732  public void onClick(DialogInterface dialog, int which) {
1733  mMemoryWarningDialog = null;
1734  }
1735  })
1736  .setNeutralButton("Save", new DialogInterface.OnClickListener() {
1737  public void onClick(DialogInterface dialog, int which) {
1738  saveOnDevice();
1739  mMemoryWarningDialog = null;
1740  }
1741  })
1742  .create();
1743  mMemoryWarningDialog.setCanceledOnTouchOutside(false);
1744  mMemoryWarningDialog.show();
1745  }
1746  else if(mMemoryWarningDialog == null && memoryUsed*3 > memoryFree && (mItemDataRecorderMode == null || !mItemDataRecorderMode.isChecked()))
1747  {
1748  mMemoryWarningDialog = new AlertDialog.Builder(getActivity())
1749  .setTitle("Warning: Memory is almost full!")
1750  .setCancelable(false)
1751  .setMessage(String.format("Free memory (%d MB) should be at least 3 times the "
1752  + "memory used (%d MB) so that some post-processing and exporting options "
1753  + "have enough memory to work correctly. If you just want to save the database "
1754  + "after scanning, you can continue until the next warning.\n\n"
1755  + "Note that showing only point clouds reduces memory needed for rendering.", memoryFree, memoryUsed))
1756  .setPositiveButton("Pause", new DialogInterface.OnClickListener() {
1757  public void onClick(DialogInterface dialog, int which) {
1758  stopMapping();
1759  }
1760  })
1761  .setNeutralButton("Continue", new DialogInterface.OnClickListener() {
1762  public void onClick(DialogInterface dialog, int which) {
1763  }
1764  })
1765  .create();
1766  mMemoryWarningDialog.setCanceledOnTouchOutside(false);
1767  mMemoryWarningDialog.show();
1768  }
1769  }
1770  }
1771 
1772 
1773  if(mState == State.STATE_MAPPING || mState == State.STATE_VISUALIZING_CAMERA)
1774  {
1775  long currentTime = System.currentTimeMillis()/1000;
1776  if(loopClosureId > 0)
1777  {
1778  if (mToast != null) mToast.cancel();
1779  mToast.setText(String.format("Loop closure detected! (%d/%d inliers)", inliers, matches));
1780  mToast.show();
1781  }
1782  else if(landmarkDetected != 0)
1783  {
1784  if (mToast != null) mToast.cancel();
1785  mToast.setText(String.format("Marker %d detected!", landmarkDetected));
1786  mToast.show();
1787  }
1788  else if(rejected > 0)
1789  {
1790  if (mToast != null) mToast.cancel();
1791  if(inliers >= Integer.parseInt(mMinInliers))
1792  {
1793  if(optimizationMaxError > 0.0f)
1794  {
1795  mToast.setText(String.format("Loop closure rejected, too high graph optimization error (%.3fm: ratio=%.3f < factor=%sx).", optimizationMaxError, optimizationMaxErrorRatio, mMaxOptimizationError));
1796  }
1797  else
1798  {
1799  mToast.setText(String.format("Loop closure rejected, graph optimization failed! You may try a different Graph Optimizer (see Mapping options)."));
1800  }
1801  }
1802  else
1803  {
1804  mToast.setText(String.format("Loop closure rejected, not enough inliers (%d/%d < %s).", inliers, matches, mMinInliers));
1805  }
1806  mToast.show();
1807  }
1808  else if(fastMovement)
1809  {
1810  if(currentTime - mLastFastMovementNotificationStamp > 3)
1811  {
1812  if (mToast != null) mToast.cancel();
1813  mToast.setText("Move slower... blurry images are not added to map (\"Settings->Mapping...->Maximum Motion Speed\" is enabled).");
1814  mToast.show();
1815  }
1816  }
1817 
1818  if(!fastMovement)
1819  {
1820  mLastFastMovementNotificationStamp = currentTime;
1821  }
1822  }
1823  }
1824 
1825  // called from jni
1826  public void updateStatsCallback(
1827  final int nodes,
1828  final int words,
1829  final int points,
1830  final int polygons,
1831  final float updateTime,
1832  final int loopClosureId,
1833  final int highestHypId,
1834  final int databaseMemoryUsed,
1835  final int inliers,
1836  final int matches,
1837  final int featuresExtracted,
1838  final float hypothesis,
1839  final int nodesDrawn,
1840  final float fps,
1841  final int rejected,
1842  final float rehearsalValue,
1843  final float optimizationMaxError,
1844  final float optimizationMaxErrorRatio,
1845  final float distanceTravelled,
1846  final int fastMovement,
1847  final int landmarkDetected,
1848  final float x,
1849  final float y,
1850  final float z,
1851  final float roll,
1852  final float pitch,
1853  final float yaw)
1854  {
1855  if(!DISABLE_LOG) Log.i(TAG, String.format("updateStatsCallback()"));
1856 
1857  final String[] statusTexts = new String[STATUS_TEXTS_SIZE];
1858 
1859  long memoryFree = getFreeMemory();
1860  statusTexts[1] = getString(R.string.memory)+(mFreeMemoryOnStart>memoryFree?mFreeMemoryOnStart-memoryFree:0);
1861  statusTexts[2] = getString(R.string.free_memory)+memoryFree;
1862 
1863  if(loopClosureId > 0)
1864  {
1865  ++mTotalLoopClosures;
1866  }
1867 
1868  mMapNodes = nodes;
1869 
1870  if(mGPSSaved)
1871  {
1872  if(mLastKnownLocation != null)
1873  {
1874  long millisec = System.currentTimeMillis() - mLastKnownLocation.getTime();
1875  if(millisec > 1000)
1876  {
1877  statusTexts[3] = getString(R.string.gps)+String.format("[too old, %d ms]", millisec);
1878  }
1879  else
1880  {
1881  statusTexts[3] = getString(R.string.gps)+
1882  String.format("%.2f %.2f %.2fm %.0fdeg %.0fm",
1883  mLastKnownLocation.getLongitude(),
1884  mLastKnownLocation.getLatitude(),
1885  mLastKnownLocation.getAltitude(),
1886  mCompassDeg,
1887  mLastKnownLocation.getAccuracy());
1888  }
1889  }
1890  else
1891  {
1892  statusTexts[3] = getString(R.string.gps)+String.format("[not yet available, %.0fdeg]", mCompassDeg);
1893  }
1894  }
1895  if(mEnvSensorsSaved)
1896  {
1897  statusTexts[4] = getString(R.string.env_sensors);
1898 
1899  if(mLastEnvSensorsSet[0])
1900  {
1901  statusTexts[4] += String.format(" %.0f dbm", mLastEnvSensors[0]);
1902  mLastEnvSensorsSet[0] = false;
1903  }
1904  if(mLastEnvSensorsSet[1])
1905  {
1906  statusTexts[4] += String.format(" %.1f %cC", mLastEnvSensors[1], '\u00B0');
1907  mLastEnvSensorsSet[1] = false;
1908  }
1909  if(mLastEnvSensorsSet[2])
1910  {
1911  statusTexts[4] += String.format(" %.1f hPa", mLastEnvSensors[2]);
1912  mLastEnvSensorsSet[2] = false;
1913  }
1914  if(mLastEnvSensorsSet[3])
1915  {
1916  statusTexts[4] += String.format(" %.0f lx", mLastEnvSensors[3]);
1917  mLastEnvSensorsSet[3] = false;
1918  }
1919  if(mLastEnvSensorsSet[4])
1920  {
1921  statusTexts[4] += String.format(" %.0f %%", mLastEnvSensors[4]);
1922  mLastEnvSensorsSet[4] = false;
1923  }
1924  }
1925 
1926  String formattedDate = new SimpleDateFormat("HH:mm:ss.SSS").format(new Date());
1927  statusTexts[5] = getString(R.string.time)+formattedDate;
1928 
1929  int index = STATUS_TEXTS_POSE_INDEX;
1930  statusTexts[index++] = getString(R.string.nodes)+nodes+" (" + nodesDrawn + " shown)";
1931  statusTexts[index++] = getString(R.string.words)+words;
1932  statusTexts[index++] = getString(R.string.database_size)+databaseMemoryUsed;
1933  statusTexts[index++] = getString(R.string.points)+points;
1934  statusTexts[index++] = getString(R.string.polygons)+polygons;
1935  statusTexts[index++] = getString(R.string.update_time)+(int)(updateTime) + " / " + (mTimeThr.compareTo("0")==0?"No Limit":mTimeThr);
1936  statusTexts[index++] = getString(R.string.features)+featuresExtracted +" / " + (mMaxFeatures.compareTo("0")==0?"No Limit":mMaxFeatures.compareTo("-1")==0?"Disabled":mMaxFeatures);
1937  statusTexts[index++] = getString(R.string.rehearsal)+(int)(rehearsalValue*100.0f);
1938  statusTexts[index++] = getString(R.string.total_loop)+mTotalLoopClosures;
1939  statusTexts[index++] = getString(R.string.inliers)+inliers;
1940  statusTexts[index++] = getString(R.string.hypothesis)+(int)(hypothesis*100.0f) +" / " + (int)(Float.parseFloat(mLoopThr)*100.0f) + " (" + (loopClosureId>0?loopClosureId:highestHypId)+")";
1941  statusTexts[index++] = getString(R.string.fps)+(int)fps+" Hz";
1942  statusTexts[index++] = getString(R.string.distance)+(int)distanceTravelled+" m";
1943  statusTexts[index++] = String.format("Pose (x,y,z): %.2f %.2f %.2f", x,y,z);
1944 
1945  runOnUiThread(new Runnable() {
1946  public void run() {
1947  updateStatsUI(loopClosureId, inliers, matches, rejected, optimizationMaxError, optimizationMaxErrorRatio, fastMovement!=0, landmarkDetected, statusTexts);
1948  }
1949  });
1950  }
1951 
1952  private void rtabmapInitEventUI(
1953  int status,
1954  String msg)
1955  {
1956  if(!DISABLE_LOG) Log.i(TAG, String.format("rtabmapInitEventsUI() status=%d msg=%s", status, msg));
1957 
1958  int optimizedMeshDetected = 0;
1959 
1960  if(msg.equals("Loading optimized cloud...done!"))
1961  {
1962  optimizedMeshDetected = 1;
1963  }
1964  else if(msg.equals("Loading optimized mesh...done!"))
1965  {
1966  optimizedMeshDetected = 2;
1967  }
1968  else if(msg.equals("Loading optimized texture mesh...done!"))
1969  {
1970  optimizedMeshDetected = 3;
1971  }
1972  if(optimizedMeshDetected > 0)
1973  {
1974  resetNoTouchTimer();
1975  mSavedRenderingType = mItemRenderingPointCloud.isChecked()?0:mItemRenderingMesh.isChecked()?1:2;
1976  if(optimizedMeshDetected==1)
1977  {
1978  mItemRenderingPointCloud.setChecked(true);
1979  }
1980  else if(optimizedMeshDetected==2)
1981  {
1982  mItemRenderingMesh.setChecked(true);
1983  }
1984  else // isOBJ
1985  {
1986  mItemRenderingTextureMesh.setChecked(true);
1987  }
1988 
1990  if(mButtonCameraView.getSelectedItemPosition() == 0)
1991  {
1992  setCamera(2);
1993  }
1994  mToast.makeText(getActivity(), String.format("Optimized mesh detected in the database, it is shown while the database is loading..."), mToast.LENGTH_LONG).show();
1995  mProgressDialog.dismiss();
1996  }
1997 
1998  if(mButtonStart!=null)
1999  {
2000  mStatusTexts[0] = getString(R.string.status)+(status == 1 && msg.isEmpty()?mState == State.STATE_CAMERA?"Camera Preview":"Idle":msg);
2001 
2002  long freeMemory = getFreeMemory();
2003  mStatusTexts[1] = getString(R.string.memory)+String.valueOf(mFreeMemoryOnStart>freeMemory?mFreeMemoryOnStart-freeMemory:0);
2004  mStatusTexts[2] = getString(R.string.free_memory)+String.valueOf(freeMemory);
2005  updateStatusTexts();
2006  }
2007  }
2008 
2009  //called from jni
2011  final int status,
2012  final String msg)
2013  {
2014  if(!DISABLE_LOG) Log.i(TAG, String.format("rtabmapInitEventCallback()"));
2015 
2016  runOnUiThread(new Runnable() {
2017  public void run() {
2018  rtabmapInitEventUI(status, msg);
2019  }
2020  });
2021  }
2022 
2023  private void updateProgressionUI(
2024  int count,
2025  int max)
2026  {
2027  if(!DISABLE_LOG) Log.i(TAG, String.format("updateProgressionUI() count=%d max=%s", count, max));
2028 
2029  mExportProgressDialog.setMax(max);
2030  mExportProgressDialog.setProgress(count);
2031  }
2032 
2033  //called from jni
2035  final int count,
2036  final int max)
2037  {
2038  if(!DISABLE_LOG) Log.i(TAG, String.format("updateProgressionCallback()"));
2039 
2040  runOnUiThread(new Runnable() {
2041  public void run() {
2042  updateProgressionUI(count, max);
2043  }
2044  });
2045  }
2046 
2047  private void cameraEventUI(
2048  int type,
2049  String key,
2050  String value)
2051  {
2063  String str = null;
2064  if(key.equals("UpstreamRelocationFiltered"))
2065  {
2066  if(mItemDebugVisibility != null && mItemDebugVisibility.isChecked()) {
2067  str = String.format("%s re-localization filtered because an acceleration of %s has been detected, which is over current threshold set in the settings.",
2068  mCameraDriver == 2?"AREngine":"ARCore", value);
2069  }
2070  }
2071  else if(key.equals("TangoServiceException"))
2072  str = String.format("Tango service exception: %s", value);
2073  else if(key.equals("FisheyeOverExposed"))
2074  ;//str = String.format("The fisheye image is over exposed with average pixel value %s px.", value);
2075  else if(key.equals("FisheyeUnderExposed"))
2076  ;//str = String.format("The fisheye image is under exposed with average pixel value %s px.", value);
2077  else if(key.equals("ColorOverExposed"))
2078  ;//str = String.format("The color image is over exposed with average pixel value %s px.", value);
2079  else if(key.equals("ColorUnderExposed"))
2080  ;//str = String.format("The color image is under exposed with average pixel value %s px.", value);
2081  else if(key.equals("CameraTango"))
2082  str = value;
2083  else if(key.equals("TooFewFeaturesTracked"))
2084  {
2085  if(!value.equals("0"))
2086  {
2087  str = String.format("Too few features (%s) were tracked in the fisheye image. This may result in poor odometry!", value);
2088  }
2089  }
2090  else if(key.equals("TooClose"))
2091  {
2092  if(mState != State.STATE_VISUALIZING_CAMERA)
2093  {
2094  str = String.format("Too close! Tip: Scan from at least ~1 meter from surfaces.", value);
2095  }
2096  }
2097  else if(key.equals("TangoPoseEventNotReceived"))
2098  {
2099  str = String.format("No valid tango pose event received since %s sec.", value);
2100  }
2101  else
2102  {
2103  str = String.format("Unknown Camera event detected!? (type=%d, key=%s, value=%s)", type, key, value);
2104  }
2105  if(str!=null)
2106  {
2107  mToast.setText(str);
2108  mToast.show();
2109  }
2110  }
2111 
2112  //called from jni
2113  public void cameraEventCallback(
2114  final int type,
2115  final String key,
2116  final String value)
2117  {
2118  runOnUiThread(new Runnable() {
2119  public void run() {
2120  cameraEventUI(type, key, value);
2121  }
2122  });
2123  }
2124 
2125  private boolean CheckTangoCoreVersion(int minVersion) {
2126  int versionNumber = 0;
2127  String packageName = TANGO_PACKAGE_NAME;
2128  try {
2129  PackageInfo pi = getApplicationContext().getPackageManager().getPackageInfo(packageName,
2130  PackageManager.GET_META_DATA);
2131  versionNumber = pi.versionCode;
2132  } catch (NameNotFoundException e) {
2133  e.printStackTrace();
2134  }
2135  return (minVersion <= versionNumber);
2136  }
2137 
2138  private RTABMapActivity getActivity() {return this;}
2139 
2140  private void standardOptimization(final boolean withStandardMeshExport) {
2141 
2142  mExportProgressDialog.setTitle("Post-Processing");
2143  mExportProgressDialog.setMessage(String.format("Please wait while optimizing..."));
2144  mExportProgressDialog.setProgress(0);
2145  mExportProgressDialog.show();
2146 
2147  updateState(State.STATE_PROCESSING);
2148  Thread workingThread = new Thread(new Runnable() {
2149  public void run() {
2150  final int loopDetected = RTABMapLib.postProcessing(nativeApplication, -1);
2151  runOnUiThread(new Runnable() {
2152  public void run() {
2153  updateState(State.STATE_IDLE);
2154  if(mExportProgressDialog.isShowing())
2155  {
2156  mExportProgressDialog.dismiss();
2157  if(loopDetected >= 0)
2158  {
2159  mTotalLoopClosures+=loopDetected;
2160  if(withStandardMeshExport)
2161  {
2162  export(true, true, false, true, 200000);
2163  }
2164  else
2165  {
2166  mProgressDialog.setTitle("Post-Processing");
2167  mProgressDialog.setMessage(String.format("Optimization done! Increasing visual appeal..."));
2168  mProgressDialog.show();
2169 
2170  if(mOpenedDatabasePath.isEmpty())
2171  {
2172  save();
2173  }
2174  }
2175  }
2176  else if(loopDetected < 0)
2177  {
2178  mToast.makeText(getActivity(), String.format("Optimization failed!"), mToast.LENGTH_LONG).show();
2179  }
2180  }
2181  else
2182  {
2183  mProgressDialog.dismiss();
2184  mToast.makeText(getActivity(), String.format("Optimization canceled"), mToast.LENGTH_LONG).show();
2185  }
2186  }
2187  });
2188  }
2189  });
2190  workingThread.start();
2191  }
2192 
2193  private Handler notouchHandler = new Handler(){
2194  public void handleMessage(Message msg) {
2195  }
2196  };
2197 
2198  private Runnable notouchCallback = new Runnable() {
2199  @Override
2200  public void run() {
2201  if(!mProgressDialog.isShowing() && !mMenuOpened)
2202  {
2203  setNavVisibility(false);
2204  mHudVisible = false;
2205  updateState(mState);
2206  }
2207  else
2208  {
2209  resetNoTouchTimer();
2210  }
2211  }
2212  };
2213 
2214  public void resetNoTouchTimer(){
2215  resetNoTouchTimer(false);
2216  }
2217 
2218  public void resetNoTouchTimer(boolean showHud){
2219  if(showHud)
2220  {
2221  mHudVisible = true;
2222  setNavVisibility(true);
2223  if(mItemSave != null)
2224  {
2225  updateState(mState);
2226  }
2227  }
2228 
2229  notouchHandler.removeCallbacks(notouchCallback);
2230  notouchHandler.postDelayed(notouchCallback, NOTOUCH_TIMEOUT);
2231 
2232  if(mGLView.getRenderMode() == GLSurfaceView.RENDERMODE_WHEN_DIRTY)
2233  {
2234  mGLView.requestRender();
2235  }
2236  }
2237 
2238  public void stopDisconnectTimer(){
2239  notouchHandler.removeCallbacks(notouchCallback);
2240  Timer timer = new Timer();
2241  timer.cancel();
2242  }
2243 
2244  private void updateState(State state)
2245  {
2246  if(mState == State.STATE_VISUALIZING && state == State.STATE_IDLE && mMapNodes > 100)
2247  {
2248  mToast.makeText(getActivity(), String.format("Re-adding %d online clouds, this may take some time...", mMapNodes), mToast.LENGTH_LONG).show();
2249  }
2250  mState = state;
2251  if(!DISABLE_LOG) Log.i(TAG, String.format("updateState() state=%s hud=%d", state.toString(), mHudVisible?1:0));
2252  mStatusTexts[0] = state.toString();
2253  switch(state)
2254  {
2255  case STATE_MAPPING:
2256  case STATE_CAMERA:
2257  mButtonLighting.setVisibility(View.INVISIBLE);
2258  mButtonWireframe.setVisibility(View.INVISIBLE);
2259  mButtonCloseVisualization.setVisibility(View.INVISIBLE);
2260  mButtonSaveOnDevice.setVisibility(View.INVISIBLE);
2261  mButtonShareOnSketchfab.setVisibility(View.INVISIBLE);
2262  mButtonLibrary.setVisibility(View.INVISIBLE);
2263  mButtonNewScan.setVisibility(View.INVISIBLE);
2264  mItemSave.setEnabled(false);
2265  mItemExport.setEnabled(false);
2266  mItemOpen.setEnabled(false);
2267  mItemNewScan.setEnabled(true);
2268  mItemPostProcessing.setEnabled(false);
2269  mItemSettings.setEnabled(false);
2270  mItemResume.setEnabled(false);
2271  mItemModes.setEnabled(mState == State.STATE_CAMERA);
2272  mItemLocalizationMode.setEnabled(true);
2273  mItemTrajectoryMode.setEnabled(true);
2274  mItemDataRecorderMode.setEnabled(true);
2275  mButtonStart.setVisibility(mState == State.STATE_CAMERA?View.VISIBLE:View.INVISIBLE);
2276  mButtonStop.setVisibility(mHudVisible && mState == State.STATE_MAPPING?View.VISIBLE:View.INVISIBLE);
2277  break;
2278  case STATE_PROCESSING:
2279  mButtonLighting.setVisibility(View.INVISIBLE);
2280  mButtonWireframe.setVisibility(View.INVISIBLE);
2281  mButtonCloseVisualization.setVisibility(View.INVISIBLE);
2282  mButtonSaveOnDevice.setVisibility(View.INVISIBLE);
2283  mButtonShareOnSketchfab.setVisibility(View.INVISIBLE);
2284  mButtonLibrary.setVisibility(View.INVISIBLE);
2285  mButtonNewScan.setVisibility(View.INVISIBLE);
2286  mItemSave.setEnabled(false);
2287  mItemExport.setEnabled(false);
2288  mItemOpen.setEnabled(false);
2289  mItemNewScan.setEnabled(false);
2290  mItemPostProcessing.setEnabled(false);
2291  mItemSettings.setEnabled(false);
2292  mItemResume.setEnabled(false);
2293  mItemModes.setEnabled(false);
2294  mButtonStart.setVisibility(View.INVISIBLE);
2295  mButtonStop.setVisibility(View.INVISIBLE);
2296  break;
2297  case STATE_VISUALIZING:
2298  case STATE_VISUALIZING_CAMERA:
2299  mButtonLighting.setVisibility(mHudVisible && !mItemRenderingPointCloud.isChecked()?View.VISIBLE:View.INVISIBLE);
2300  mButtonWireframe.setVisibility(mHudVisible && !mItemRenderingPointCloud.isChecked()?View.VISIBLE:View.INVISIBLE);
2301  mButtonCloseVisualization.setVisibility(mHudVisible && mState != State.STATE_VISUALIZING_CAMERA?View.VISIBLE:View.INVISIBLE);
2302  mButtonCloseVisualization.setEnabled(true);
2303  mButtonSaveOnDevice.setVisibility(mHudVisible && mState != State.STATE_VISUALIZING_CAMERA?View.VISIBLE:View.INVISIBLE);
2304  //mButtonShareOnSketchfab.setVisibility(mHudVisible && mState != State.STATE_VISUALIZING_CAMERA?View.VISIBLE:View.INVISIBLE);
2305  mButtonLibrary.setVisibility(View.INVISIBLE);
2306  mButtonNewScan.setVisibility(View.INVISIBLE);
2307  mItemSave.setEnabled(mState != State.STATE_VISUALIZING_CAMERA);
2308  mItemExport.setEnabled(!mItemDataRecorderMode.isChecked() && mState != State.STATE_VISUALIZING_CAMERA);
2309  mItemOpen.setEnabled(mState != State.STATE_VISUALIZING_CAMERA);
2310  mItemNewScan.setEnabled(mState != State.STATE_VISUALIZING_CAMERA);
2311  mItemPostProcessing.setEnabled(false);
2312  mItemSettings.setEnabled(mState != State.STATE_VISUALIZING_CAMERA);
2313  mItemResume.setEnabled(mMapNodes>0 && mState == State.STATE_VISUALIZING);
2314  mItemModes.setEnabled(mState == State.STATE_VISUALIZING);
2315  mItemLocalizationMode.setEnabled(true);
2316  mItemTrajectoryMode.setEnabled(false);
2317  mItemDataRecorderMode.setEnabled(false);
2318  mButtonStart.setVisibility(View.INVISIBLE);
2319  mButtonStop.setVisibility(mHudVisible && mState == State.STATE_VISUALIZING_CAMERA?View.VISIBLE:View.INVISIBLE);
2320  break;
2321  case STATE_VISUALIZING_WHILE_LOADING:
2322  mButtonLighting.setVisibility(mHudVisible && !mItemRenderingPointCloud.isChecked()?View.VISIBLE:View.INVISIBLE);
2323  mButtonWireframe.setVisibility(mHudVisible && !mItemRenderingPointCloud.isChecked()?View.VISIBLE:View.INVISIBLE);
2324  mButtonCloseVisualization.setVisibility(mHudVisible?View.VISIBLE:View.INVISIBLE);
2325  mButtonCloseVisualization.setEnabled(false);
2326  mButtonSaveOnDevice.setVisibility(View.INVISIBLE);
2327  mButtonShareOnSketchfab.setVisibility(View.INVISIBLE);
2328  mButtonLibrary.setVisibility(View.INVISIBLE);
2329  mButtonNewScan.setVisibility(View.INVISIBLE);
2330  mItemSave.setEnabled(false);
2331  mItemExport.setEnabled(false);
2332  mItemOpen.setEnabled(false);
2333  mItemPostProcessing.setEnabled(false);
2334  mItemSettings.setEnabled(false);
2335  mItemResume.setEnabled(false);
2336  mItemModes.setEnabled(false);
2337  mButtonStart.setVisibility(View.INVISIBLE);
2338  mButtonStop.setVisibility(View.INVISIBLE);
2339  break;
2340  default: // IDLE // WELCOME
2341  mButtonLighting.setVisibility(View.INVISIBLE);
2342  mButtonWireframe.setVisibility(View.INVISIBLE);
2343  mButtonCloseVisualization.setVisibility(View.INVISIBLE);
2344  mButtonSaveOnDevice.setVisibility(View.INVISIBLE);
2345  mButtonShareOnSketchfab.setVisibility(View.INVISIBLE);
2346  mButtonLibrary.setVisibility(mState==State.STATE_WELCOME?View.VISIBLE:View.INVISIBLE);
2347  mButtonNewScan.setVisibility(mState==State.STATE_WELCOME?View.VISIBLE:View.INVISIBLE);
2348  mItemSave.setEnabled(mMapNodes>0);
2349  mItemExport.setEnabled(mMapNodes>0);
2350  mItemOpen.setEnabled(true);
2351  mItemNewScan.setEnabled(true);
2352  mItemPostProcessing.setEnabled(mMapNodes>0);
2353  mItemSettings.setEnabled(true);
2354  mItemResume.setEnabled(mMapNodes>0);
2355  mItemModes.setEnabled(true);
2356  mButtonStart.setVisibility(View.INVISIBLE);
2357  mButtonStop.setVisibility(View.INVISIBLE);
2358  mItemLocalizationMode.setEnabled(true);
2359  mItemDataRecorderMode.setEnabled(true);
2360  mItemTrajectoryMode.setEnabled(true);
2361  break;
2362  }
2363  mButtonCameraView.setVisibility(mHudVisible?View.VISIBLE:View.INVISIBLE);
2364  mButtonBackfaceShown.setVisibility(mHudVisible && (mItemRenderingMesh.isChecked() || mItemRenderingTextureMesh.isChecked())?View.VISIBLE:View.INVISIBLE);
2365  mSeekBarOrthoCut.setVisibility(mHudVisible && mButtonCameraView.getSelectedItemPosition() == 3?View.VISIBLE:View.INVISIBLE);
2366  mSeekBarGrid.setVisibility(mHudVisible && mSeekBarGrid.isEnabled() && mButtonCameraView.getSelectedItemPosition() == 3?View.VISIBLE:View.INVISIBLE);
2367 
2368  if(mState != State.STATE_MAPPING && mState != State.STATE_CAMERA && mState!=State.STATE_VISUALIZING_CAMERA)
2369  {
2370  mGLView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
2371  mGLView.requestRender();
2372  }
2373  else
2374  {
2375  mGLView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
2376  }
2377 
2378  if(mState == State.STATE_WELCOME && mIntentDbToOpen != null)
2379  {
2380  openDatabase(mIntentDbToOpen, false);
2381  mIntentDbToOpen = null;
2382  }
2383  }
2384 
2385  private void startMapping() {
2386  if(!DISABLE_LOG) Log.i(TAG, String.format("startMapping()"));
2387 
2388  updateState(State.STATE_MAPPING);
2389 
2390  if(mMemoryWarningDialog != null)
2391  {
2392  mMemoryWarningDialog.dismiss();
2393  mMemoryWarningDialog=null;
2394  }
2395  RTABMapLib.setPausedMapping(nativeApplication, false);
2396  mLastFastMovementNotificationStamp = System.currentTimeMillis()/1000;
2397 
2398  if(mItemDataRecorderMode.isChecked())
2399  {
2400  mToast.makeText(getActivity(), String.format("Data Recorder Mode: no map is created, only raw data is recorded."), mToast.LENGTH_LONG).show();
2401  }
2402  else if(mMapNodes>0)
2403  {
2404  if(mItemLocalizationMode!=null && mItemLocalizationMode.isChecked())
2405  {
2406  mToast.makeText(getActivity(), String.format("Localization mode"), mToast.LENGTH_LONG).show();
2407  }
2408  else
2409  {
2410  mToast.makeText(getActivity(), String.format("On resume, a new map is created. Tip: Try relocalizing in the previous area."), mToast.LENGTH_LONG).show();
2411  }
2412  }
2413  else if(mMapNodes==0 && mItemLocalizationMode!=null && mItemLocalizationMode.isChecked())
2414  {
2415  mItemLocalizationMode.setChecked(false);
2416  RTABMapLib.setLocalizationMode(nativeApplication, false);
2417  mToast.makeText(getActivity(), String.format("Disabled localization mode as the map is empty, now mapping..."), mToast.LENGTH_LONG).show();
2418  }
2419  }
2420 
2421  private void stopCamera() {
2422 
2423  mProgressDialog.setTitle("");
2424  mProgressDialog.setMessage("Stopping camera...");
2425  mProgressDialog.show();
2426 
2427  if(mState == State.STATE_VISUALIZING_CAMERA)
2428  {
2429  RTABMapLib.setPausedMapping(nativeApplication, true);
2430  updateState(State.STATE_VISUALIZING);
2431  }
2432  else
2433  {
2434  if(mMapNodes==0)
2435  {
2436  updateState(State.STATE_WELCOME);
2437  }
2438  else
2439  {
2440  updateState(State.STATE_IDLE);
2441  }
2442  }
2443 
2444  if(mArCoreCamera != null)
2445  {
2446  synchronized (this) {
2447  mRenderer.setCamera(null);
2448  mArCoreCamera.close();
2449  mArCoreCamera = null;
2450  }
2451  }
2452 
2453  Thread stopThread = new Thread(new Runnable() {
2454  public void run() {
2455  if(!DISABLE_LOG) Log.i(TAG, String.format("stopCamera()"));
2456  RTABMapLib.stopCamera(nativeApplication);
2457  if(mCameraServiceConnectionUsed)
2458  {
2459  if(!DISABLE_LOG) Log.i(TAG, String.format("unbindService"));
2460  getActivity().unbindService(mCameraServiceConnection);
2461  }
2462  mCameraServiceConnectionUsed = false;
2463 
2464  runOnUiThread(new Runnable() {
2465  public void run() {
2466  setCamera(2);
2467  if(!DISABLE_LOG) Log.i(TAG, String.format("stopMapping(): runOnUiThread"));
2468  mProgressDialog.dismiss();
2469  }
2470  });
2471  }
2472  });
2473  stopThread.start();
2474  }
2475 
2476  private void stopMapping() {
2477 
2478  mProgressDialog.setTitle("");
2479  mProgressDialog.setMessage("Stopping camera...");
2480  mProgressDialog.show();
2481 
2482  updateState(State.STATE_IDLE);
2483 
2484  if(mArCoreCamera != null)
2485  {
2486  synchronized (this) {
2487  mRenderer.setCamera(null);
2488  mArCoreCamera.close();
2489  mArCoreCamera = null;
2490  }
2491  }
2492 
2493  Thread stopThread = new Thread(new Runnable() {
2494  public void run() {
2495  if(!DISABLE_LOG) Log.i(TAG, String.format("setPausedMapping()"));
2496  RTABMapLib.setPausedMapping(nativeApplication, true);
2497  if(!DISABLE_LOG) Log.i(TAG, String.format("stopCamera()"));
2498  RTABMapLib.stopCamera(nativeApplication);
2499  if(mCameraServiceConnectionUsed)
2500  {
2501  if(!DISABLE_LOG) Log.i(TAG, String.format("unbindService"));
2502  getActivity().unbindService(mCameraServiceConnection);
2503  }
2504  mCameraServiceConnectionUsed = false;
2505 
2506  runOnUiThread(new Runnable() {
2507  public void run() {
2508  if(!DISABLE_LOG) Log.i(TAG, String.format("stopMapping(): runOnUiThread"));
2509  mProgressDialog.dismiss();
2510 
2511  setCamera(2);
2512 
2513  long freeMemory = getFreeMemory();
2514  mStatusTexts[1] = getString(R.string.memory)+String.valueOf(mFreeMemoryOnStart>freeMemory?mFreeMemoryOnStart-freeMemory:0);
2515  mStatusTexts[2] = getString(R.string.free_memory)+String.valueOf(freeMemory);
2516  updateStatusTexts();
2517 
2518  mDateOnPause = new Date();
2519 
2520  long memoryFree = getFreeMemory();
2521  if(!mOnPause && !mItemLocalizationMode.isChecked() && !mItemDataRecorderMode.isChecked() && memoryFree >= 100 && mMapNodes>2)
2522  {
2523  if(!DISABLE_LOG) Log.i(TAG, String.format("Do standard processing>?"));
2524  // Do standard post processing?
2525  AlertDialog d2 = new AlertDialog.Builder(getActivity())
2526  .setCancelable(false)
2527  .setTitle("Mapping Stopped! Optimize Now?")
2528  .setMessage("Do you want to do standard graph and mesh optimizations now? This can be also done later using \"Optimize\" and \"Export\" menus.")
2529  .setNeutralButton("Only Graph", new DialogInterface.OnClickListener() {
2530  public void onClick(DialogInterface dialog, int which) {
2531  standardOptimization(false);
2532  }
2533  })
2534  .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
2535  public void onClick(DialogInterface dialog, int which) {
2536  standardOptimization(true);
2537  }
2538  })
2539  .setNegativeButton("No", new DialogInterface.OnClickListener() {
2540  public void onClick(DialogInterface dialog, int which) {
2541  if(mOpenedDatabasePath.isEmpty())
2542  {
2543  save();
2544  }
2545  }
2546  })
2547  .create();
2548  d2.setCanceledOnTouchOutside(false);
2549  d2.show();
2550  }
2551  }
2552  });
2553  }
2554  });
2555  stopThread.start();
2556  }
2557 
2558  public boolean onOptionsItemSelected(MenuItem item) {
2559  resetNoTouchTimer();
2560  if(!DISABLE_LOG) Log.i(TAG, "called onOptionsItemSelected; selected item: " + item);
2561  int itemId = item.getItemId();
2562  if (itemId == R.id.post_processing_standard)
2563  {
2564  standardOptimization(false);
2565  }
2566  else if (itemId == R.id.detect_more_loop_closures)
2567  {
2568  mProgressDialog.setTitle("Post-Processing");
2569  mProgressDialog.setMessage(String.format("Please wait while detecting more loop closures..."));
2570  mProgressDialog.show();
2571  updateState(State.STATE_PROCESSING);
2572  Thread workingThread = new Thread(new Runnable() {
2573  public void run() {
2574  final int loopDetected = RTABMapLib.postProcessing(nativeApplication, 2);
2575  runOnUiThread(new Runnable() {
2576  public void run() {
2577  mProgressDialog.dismiss();
2578  if(loopDetected >= 0)
2579  {
2580  mTotalLoopClosures+=loopDetected;
2581  mToast.makeText(getActivity(), String.format("Detection done! %d new loop closure(s) added.", loopDetected), mToast.LENGTH_SHORT).show();
2582  }
2583  else if(loopDetected < 0)
2584  {
2585  mToast.makeText(getActivity(), String.format("Detection failed!"), mToast.LENGTH_SHORT).show();
2586  }
2587  updateState(State.STATE_IDLE);
2588  }
2589  });
2590  }
2591  });
2592  workingThread.start();
2593  }
2594  else if (itemId == R.id.global_graph_optimization)
2595  {
2596  mProgressDialog.setTitle("Post-Processing");
2597  mProgressDialog.setMessage(String.format("Global graph optimization..."));
2598  mProgressDialog.show();
2599  updateState(State.STATE_PROCESSING);
2600  Thread workingThread = new Thread(new Runnable() {
2601  public void run() {
2602  final int value = RTABMapLib.postProcessing(nativeApplication, 0);
2603  runOnUiThread(new Runnable() {
2604  public void run() {
2605  mProgressDialog.dismiss();
2606  if(value >= 0)
2607  {
2608  mToast.makeText(getActivity(), String.format("Optimization done!"), mToast.LENGTH_SHORT).show();
2609  }
2610  else if(value < 0)
2611  {
2612  mToast.makeText(getActivity(), String.format("Optimization failed!"), mToast.LENGTH_SHORT).show();
2613  }
2614  updateState(State.STATE_IDLE);
2615  }
2616  });
2617  }
2618  });
2619  workingThread.start();
2620  }
2621  else if (itemId == R.id.polygons_filtering)
2622  {
2623  mProgressDialog.setTitle("Post-Processing");
2624  mProgressDialog.setMessage(String.format("Noise filtering..."));
2625  mProgressDialog.show();
2626  RTABMapLib.postProcessing(nativeApplication, 4);
2627  }
2628  else if (itemId == R.id.gain_compensation_fast)
2629  {
2630  mProgressDialog.setTitle("Post-Processing");
2631  mProgressDialog.setMessage(String.format("Adjusting Colors (Fast)..."));
2632  mProgressDialog.show();
2633  RTABMapLib.postProcessing(nativeApplication, 5);
2634  }
2635  else if (itemId == R.id.gain_compensation_full)
2636  {
2637  mProgressDialog.setTitle("Post-Processing");
2638  mProgressDialog.setMessage(String.format("Adjusting Colors (Full)..."));
2639  mProgressDialog.show();
2640  RTABMapLib.postProcessing(nativeApplication, 6);
2641  }
2642  else if (itemId == R.id.bilateral_filtering)
2643  {
2644  mProgressDialog.setTitle("Post-Processing");
2645  mProgressDialog.setMessage(String.format("Mesh smoothing..."));
2646  mProgressDialog.show();
2647  RTABMapLib.postProcessing(nativeApplication, 7);
2648  }
2649  else if (itemId == R.id.sba)
2650  {
2651  mProgressDialog.setTitle("Post-Processing");
2652  mProgressDialog.setMessage(String.format("Bundle adjustement..."));
2653  mProgressDialog.show();
2654 
2655  Thread workingThread = new Thread(new Runnable() {
2656  public void run() {
2657  final int value = RTABMapLib.postProcessing(nativeApplication, 1);
2658  runOnUiThread(new Runnable() {
2659  public void run() {
2660  mProgressDialog.dismiss();
2661  if(value >= 0)
2662  {
2663  mToast.makeText(getActivity(), String.format("Optimization done!"), mToast.LENGTH_SHORT).show();
2664  }
2665  else if(value < 0)
2666  {
2667  mToast.makeText(getActivity(), String.format("Optimization failed!"), mToast.LENGTH_SHORT).show();
2668  }
2669  }
2670  });
2671  }
2672  });
2673  workingThread.start();
2674  }
2675  else if(itemId == R.id.status)
2676  {
2677  item.setChecked(!item.isChecked());
2678  updateStatusTexts();
2679  }
2680  else if(itemId == R.id.debug)
2681  {
2682  item.setChecked(!item.isChecked());
2683  updateStatusTexts();
2684  }
2685  else if(itemId == R.id.mesh || itemId == R.id.texture_mesh || itemId == R.id.point_cloud)
2686  {
2687  item.setChecked(true);
2689  nativeApplication,
2690  mItemRenderingMesh.isChecked() || mItemRenderingTextureMesh.isChecked(),
2691  mItemRenderingTextureMesh.isChecked());
2692 
2693  resetNoTouchTimer();
2694 
2695  if(mState != State.STATE_VISUALIZING)
2696  {
2697  // save preference
2698  int type = mItemRenderingPointCloud.isChecked()?0:mItemRenderingMesh.isChecked()?1:2;
2699  SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
2700  SharedPreferences.Editor editor = sharedPref.edit();
2701  editor.putInt(getString(R.string.pref_key_rendering), type);
2702  // Commit the edits!
2703  editor.commit();
2704  }
2705  }
2706  else if(itemId == R.id.map_shown)
2707  {
2708  item.setChecked(!item.isChecked());
2709  RTABMapLib.setMapCloudShown(nativeApplication, item.isChecked());
2710  }
2711  else if(itemId == R.id.odom_shown)
2712  {
2713  item.setChecked(!item.isChecked());
2714  RTABMapLib.setOdomCloudShown(nativeApplication, item.isChecked());
2715  }
2716  else if(itemId == R.id.localization_mode)
2717  {
2718  item.setChecked(!item.isChecked());
2719  RTABMapLib.setLocalizationMode(nativeApplication, item.isChecked());
2720  }
2721  else if(itemId == R.id.trajectory_mode)
2722  {
2723  item.setChecked(!item.isChecked());
2724  RTABMapLib.setTrajectoryMode(nativeApplication, item.isChecked());
2725  setCamera(item.isChecked()?2:1);
2726  }
2727  else if(itemId == R.id.graph_optimization)
2728  {
2729  item.setChecked(!item.isChecked());
2730  RTABMapLib.setGraphOptimization(nativeApplication, item.isChecked());
2731  }
2732  else if(itemId == R.id.graph_visible)
2733  {
2734  item.setChecked(!item.isChecked());
2735  RTABMapLib.setGraphVisible(nativeApplication, item.isChecked());
2736  }
2737  else if(itemId == R.id.grid_visible)
2738  {
2739  item.setChecked(!item.isChecked());
2740  mSeekBarGrid.setEnabled(item.isChecked());
2741  mSeekBarGrid.setVisibility(mHudVisible && mSeekBarGrid.isEnabled()&&mButtonCameraView.getSelectedItemPosition() == 3?View.VISIBLE:View.INVISIBLE);
2742  RTABMapLib.setGridVisible(nativeApplication, item.isChecked());
2743  }
2744  else if (itemId == R.id.save)
2745  {
2746  save();
2747  }
2748  else if(itemId == R.id.resume)
2749  {
2750  resumeScan();
2751  }
2752  else if(itemId == R.id.new_scan)
2753  {
2754  newScan();
2755  }
2756  else if(itemId == R.id.data_recorder)
2757  {
2758  final boolean dataRecorderOldState = item.isChecked();
2759  AlertDialog d2 = new AlertDialog.Builder(getActivity())
2760  .setCancelable(false)
2761  .setTitle("Data Recorder Mode")
2762  .setMessage("Changing from/to data recorder mode will close the current session. Do you want to continue?")
2763  .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
2764  public void onClick(DialogInterface dialog, int which) {
2765  // reset
2766  mTotalLoopClosures = 0;
2767  int index = STATUS_TEXTS_POSE_INDEX;
2768  mMapNodes = 0;
2769  mStatusTexts[index++] = getString(R.string.nodes)+0;
2770  mStatusTexts[index++] = getString(R.string.words)+0;
2771  mStatusTexts[index++] = getString(R.string.database_size)+0;
2772  mStatusTexts[index++] = getString(R.string.points)+0;
2773  mStatusTexts[index++] = getString(R.string.polygons)+0;
2774  mStatusTexts[index++] = getString(R.string.update_time)+0;
2775  mStatusTexts[index++] = getString(R.string.features)+0;
2776  mStatusTexts[index++] = getString(R.string.rehearsal)+0;
2777  mStatusTexts[index++] = getString(R.string.total_loop)+0;
2778  mStatusTexts[index++] = getString(R.string.inliers)+0;
2779  mStatusTexts[index++] = getString(R.string.hypothesis)+0;
2780  mStatusTexts[index++] = getString(R.string.fps)+0;
2781  mStatusTexts[index++] = getString(R.string.distance)+0;
2782  mStatusTexts[index++] = String.format("Pose (x,y,z): 0 0 0");
2783  updateStatusTexts();
2784 
2785  mItemDataRecorderMode.setChecked(!dataRecorderOldState);
2786  RTABMapLib.setDataRecorderMode(nativeApplication, mItemDataRecorderMode.isChecked());
2787 
2788  mOpenedDatabasePath = "";
2789  SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
2790  boolean databaseInMemory = sharedPref.getBoolean(getString(R.string.pref_key_db_in_memory), Boolean.parseBoolean(getString(R.string.pref_default_db_in_memory)));
2791  String tmpDatabase = mWorkingDirectory+RTABMAP_TMP_DB;
2792  RTABMapLib.openDatabase(nativeApplication, tmpDatabase, databaseInMemory, false, true);
2793 
2794  mItemLocalizationMode.setEnabled(!mItemDataRecorderMode.isChecked());
2795 
2796  if(mItemDataRecorderMode.isChecked())
2797  {
2798  mToast.makeText(getActivity(), String.format("Data recorder mode activated! Tip: You can increase data update rate in Parameters menu under Mapping options."), mToast.LENGTH_LONG).show();
2799  }
2800  else
2801  {
2802  mToast.makeText(getActivity(), String.format("Data recorder mode deactivated!"), mToast.LENGTH_LONG).show();
2803  }
2804  }
2805  })
2806  .setNegativeButton("No", new DialogInterface.OnClickListener() {
2807  public void onClick(DialogInterface dialog, int which) {
2808  dialog.dismiss();
2809  }
2810  })
2811  .create();
2812  d2.setCanceledOnTouchOutside(false);
2813  d2.show();
2814  }
2815  else if(itemId == R.id.export_point_cloud ||
2816  itemId == R.id.export_point_cloud_highrez)
2817  {
2818  final boolean regenerateCloud = itemId == R.id.export_point_cloud_highrez;
2819 
2820  export(false, false, regenerateCloud, false, 0);
2821  }
2822  else if(itemId == R.id.export_optimized_mesh ||
2823  itemId == R.id.export_optimized_mesh_texture)
2824  {
2825  final boolean isOBJ = itemId == R.id.export_optimized_mesh_texture;
2826 
2827  RelativeLayout linearLayout = new RelativeLayout(this);
2828  final NumberPicker aNumberPicker = new NumberPicker(this);
2829  aNumberPicker.setMaxValue(9);
2830  aNumberPicker.setMinValue(0);
2831  aNumberPicker.setWrapSelectorWheel(false);
2832  aNumberPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
2833  aNumberPicker.setFormatter(new NumberPicker.Formatter() {
2834  @Override
2835  public String format(int i) {
2836  if(i==0)
2837  {
2838  return "No Limit";
2839  }
2840  return String.format("%d00 000", i);
2841  }
2842  });
2843  aNumberPicker.setValue(2);
2844 
2845  // Fix to correctly show value on first render
2846  try {
2847  Method method = aNumberPicker.getClass().getDeclaredMethod("changeValueByOne", boolean.class);
2848  method.setAccessible(true);
2849  method.invoke(aNumberPicker, true);
2850  } catch (NoSuchMethodException e) {
2851  e.printStackTrace();
2852  } catch (IllegalArgumentException e) {
2853  e.printStackTrace();
2854  } catch (IllegalAccessException e) {
2855  e.printStackTrace();
2856  } catch (InvocationTargetException e) {
2857  e.printStackTrace();
2858  }
2859 
2860 
2861  RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(50, 50);
2862  RelativeLayout.LayoutParams numPicerParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
2863  numPicerParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
2864 
2865  linearLayout.setLayoutParams(params);
2866  linearLayout.addView(aNumberPicker,numPicerParams);
2867 
2868  AlertDialog ad = new AlertDialog.Builder(this)
2869  .setTitle("Maximum polygons")
2870  .setView(linearLayout)
2871  .setCancelable(false)
2872  .setPositiveButton("Ok",
2873  new DialogInterface.OnClickListener() {
2874  public void onClick(DialogInterface dialog,
2875  int id) {
2876  export(isOBJ, true, false, true, aNumberPicker.getValue()*100000);
2877  }
2878  })
2879  .setNegativeButton("Cancel",
2880  new DialogInterface.OnClickListener() {
2881  public void onClick(DialogInterface dialog,
2882  int id) {
2883  dialog.cancel();
2884  }
2885  }).create();
2886  ad.setCanceledOnTouchOutside(false);
2887  ad.show();
2888  }
2889  else if(itemId == R.id.open)
2890  {
2891  openDatabase();
2892  }
2893  else if(itemId == R.id.settings)
2894  {
2895  Intent intent = new Intent(getActivity(), SettingsActivity.class);
2896  startActivity(intent);
2897  }
2898  else if(itemId == R.id.about)
2899  {
2900  AboutDialog about = new AboutDialog(this);
2901  about.setTitle("About RTAB-Map");
2902  about.show();
2903  }
2904 
2905  return true;
2906  }
2907 
2908  private void resumeScan()
2909  {
2910  setCamera(mState==State.STATE_VISUALIZING?0:1);
2911  startCamera(String.format("Hold Tight! Initializing Camera Service...\n"
2912  + "Tip: If the camera is still drifting just after the mapping has started, do \"Reset\"."));
2913  }
2914 
2915  private void newScan() {
2916 
2917  if(mState == State.STATE_VISUALIZING)
2918  {
2919  mMapNodes = 0; // To avoid "re-adding clouds..." message when changing state from VIS to IDLE
2920  closeVisualization();
2921  }
2922 
2923  mTotalLoopClosures = 0;
2924 
2925  int index = STATUS_TEXTS_POSE_INDEX;
2926  mMapNodes = 0;
2927  mStatusTexts[index++] = getString(R.string.nodes)+0;
2928  mStatusTexts[index++] = getString(R.string.words)+0;
2929  mStatusTexts[index++] = getString(R.string.database_size)+0;
2930  mStatusTexts[index++] = getString(R.string.points)+0;
2931  mStatusTexts[index++] = getString(R.string.polygons)+0;
2932  mStatusTexts[index++] = getString(R.string.update_time)+0;
2933  mStatusTexts[index++] = getString(R.string.features)+0;
2934  mStatusTexts[index++] = getString(R.string.rehearsal)+0;
2935  mStatusTexts[index++] = getString(R.string.total_loop)+0;
2936  mStatusTexts[index++] = getString(R.string.inliers)+0;
2937  mStatusTexts[index++] = getString(R.string.hypothesis)+0;
2938  mStatusTexts[index++] = getString(R.string.fps)+0;
2939  mStatusTexts[index++] = getString(R.string.distance)+0;
2940  mStatusTexts[index++] = String.format("Pose (x,y,z): 0 0 0");
2941  updateStatusTexts();
2942 
2943  mOpenedDatabasePath = "";
2944  SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
2945  boolean databaseInMemory = sharedPref.getBoolean(getString(R.string.pref_key_db_in_memory), Boolean.parseBoolean(getString(R.string.pref_default_db_in_memory)));
2946  final String tmpDatabase = mWorkingDirectory+RTABMAP_TMP_DB;
2947 
2948  File newFile = new File(tmpDatabase);
2949  final int fileSizeMB = (int)newFile.length()/(1024 * 1024);
2950  if(!(mState == State.STATE_CAMERA || mState ==State.STATE_MAPPING) &&
2951  newFile.exists() &&
2952  fileSizeMB>1) // >1MB
2953  {
2954  AlertDialog d2 = new AlertDialog.Builder(getActivity())
2955  .setCancelable(false)
2956  .setTitle("Recovery")
2957  .setMessage(String.format("The previous session (%d MB) was not correctly saved, do you want to recover it?", fileSizeMB))
2958  .setNegativeButton("Ignore", new DialogInterface.OnClickListener() {
2959  public void onClick(DialogInterface dialog, int which) {
2960  (new File(tmpDatabase)).delete();
2961  newScan();
2962  }
2963  })
2964  .setNeutralButton("Cancel", new DialogInterface.OnClickListener() {
2965  public void onClick(DialogInterface dialog, int which) {
2966  // do nothing
2967  }
2968  })
2969  .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
2970  public void onClick(DialogInterface dialog, int which) {
2971  final String fileName = new SimpleDateFormat("yyMMdd-HHmmss").format(new Date()) + ".db";
2972  final String outputDbPath = mWorkingDirectory + fileName;
2973 
2974  mExportProgressDialog.setTitle("Recovering");
2975  mExportProgressDialog.setMessage(String.format("Please wait while recovering data..."));
2976  mExportProgressDialog.setProgress(0);
2977 
2978  final State previousState = mState;
2979 
2980  mExportProgressDialog.show();
2981  updateState(State.STATE_PROCESSING);
2982 
2983  Thread exportThread = new Thread(new Runnable() {
2984  public void run() {
2985 
2986  final long startTime = System.currentTimeMillis()/1000;
2987 
2988  final boolean success = RTABMapLib.recover(
2989  nativeApplication,
2990  tmpDatabase,
2991  outputDbPath);
2992  runOnUiThread(new Runnable() {
2993  public void run() {
2994  if(mExportProgressDialog.isShowing())
2995  {
2996  if(success)
2997  {
2998  AlertDialog d2 = new AlertDialog.Builder(getActivity())
2999  .setCancelable(false)
3000  .setTitle("Database saved!")
3001  .setMessage(String.format("Database \"%s\" (%d MB) successfully saved!", fileName, fileSizeMB))
3002  .setPositiveButton("OK", new DialogInterface.OnClickListener() {
3003  public void onClick(DialogInterface dialog, int which) {
3004  openDatabase(fileName, false);
3005  }
3006  })
3007  .create();
3008  d2.setCanceledOnTouchOutside(true);
3009  d2.show();
3010  }
3011  else
3012  {
3013  updateState(previousState);
3014  mToast.makeText(getActivity(), String.format("Recovery failed!"), mToast.LENGTH_LONG).show();
3015  }
3016  mExportProgressDialog.dismiss();
3017  }
3018  else
3019  {
3020  mToast.makeText(getActivity(), String.format("Recovery canceled"), mToast.LENGTH_LONG).show();
3021  updateState(previousState);
3022  }
3023  }
3024  });
3025  }
3026  });
3027  exportThread.start();
3028 
3029  refreshSystemMediaScanDataBase(getActivity(), outputDbPath);
3030  }
3031  })
3032  .create();
3033  d2.setCanceledOnTouchOutside(false);
3034  d2.show();
3035  }
3036  else
3037  {
3038  RTABMapLib.openDatabase(nativeApplication, tmpDatabase, databaseInMemory, false, true);
3039 
3040  if(!(mState == State.STATE_CAMERA || mState ==State.STATE_MAPPING))
3041  {
3042  setCamera(0);
3043  startCamera(String.format("Hold Tight! Initializing Camera Service...\n"
3044  + "Tip: If the camera is still drifting just after the mapping has started, do \"Reset\"."));
3045  }
3046  }
3047  }
3048 
3049 
3050  private void openDatabase()
3051  {
3052  final String[] files = Util.loadFileList(mWorkingDirectory, true);
3053  if(files.length > 0)
3054  {
3055  String[] filesWithSize = new String[files.length];
3056  for(int i = 0; i<filesWithSize.length; ++i)
3057  {
3058  File filePath = new File(mWorkingDirectory+files[i]);
3059  long mb = filePath.length()/(1024*1024);
3060  filesWithSize[i] = files[i] + " ("+mb+" MB)";
3061  }
3062 
3063  ArrayList<HashMap<String, String> > arrayList = new ArrayList<HashMap<String, String> >();
3064  for (int i = 0; i < filesWithSize.length; i++) {
3065  HashMap<String, String> hashMap = new HashMap<String, String>();//create a hashmap to store the data in key value pair
3066  hashMap.put("name", filesWithSize[i]);
3067  hashMap.put("path", mWorkingDirectory + files[i]);
3068  arrayList.add(hashMap);//add the hashmap into arrayList
3069  }
3070  String[] from = {"name", "path"};//string array
3071  int[] to = {R.id.textView, R.id.imageView};//int array of views id's
3072  DatabaseListArrayAdapter simpleAdapter = new DatabaseListArrayAdapter(this, arrayList, R.layout.database_list, from, to);//Create object and set the parameters for simpleAdapter
3073 
3074  AlertDialog.Builder builder = new AlertDialog.Builder(this);
3075  builder.setCancelable(true);
3076  builder.setTitle("Choose Your File (*.db)");
3077  builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
3078  public void onClick(DialogInterface dialog, int whichIn) {
3079  // do nothing
3080  }
3081  });
3082  builder.setAdapter(simpleAdapter, new DialogInterface.OnClickListener() {
3083  //builder.setItems(filesWithSize, new DialogInterface.OnClickListener() {
3084  public void onClick(DialogInterface dialog, final int which) {
3085 
3086  // Adjust color now?
3087  AlertDialog d2 = new AlertDialog.Builder(getActivity())
3088  .setCancelable(false)
3089  .setTitle("Opening database...")
3090  .setMessage("Do you want to adjust colors now?\nThis can be done later under Optimize menu.")
3091  .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
3092  public void onClick(DialogInterface dialog, int whichIn) {
3093  openDatabase(files[which], true);
3094  }
3095  })
3096  .setNeutralButton("No", new DialogInterface.OnClickListener() {
3097  public void onClick(DialogInterface dialog, int whichIn) {
3098  openDatabase(files[which], false);
3099  }
3100  })
3101  .create();
3102  d2.setCanceledOnTouchOutside(false);
3103  d2.show();
3104  return;
3105  }
3106  });
3107 
3108  final AlertDialog ad = builder.create(); //don't show dialog yet
3109  ad.setCanceledOnTouchOutside(true);
3110  ad.setOnShowListener(new OnShowListener()
3111  {
3112  @Override
3113  public void onShow(DialogInterface dialog)
3114  {
3115  ListView lv = ad.getListView();
3116  ad.registerForContextMenu(lv);
3117  lv.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
3118 
3119  @Override
3120  public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
3121 
3122  if (v.getId()==ad.getListView().getId()) {
3123  AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
3124  final int position = info.position;
3125  menu.setHeaderTitle(files[position]);
3126  menu.add(Menu.NONE, 0, 0, "Rename").setOnMenuItemClickListener(new OnMenuItemClickListener() {
3127  @Override
3128  public boolean onMenuItemClick(MenuItem item) {
3129  AlertDialog.Builder builderRename = new AlertDialog.Builder(getActivity());
3130  builderRename.setCancelable(false);
3131  builderRename.setTitle("RTAB-Map Database Name (*.db):");
3132  final EditText input = new EditText(getActivity());
3133  input.setInputType(InputType.TYPE_CLASS_TEXT);
3134  input.setText("");
3135  input.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
3136  input.setSelectAllOnFocus(true);
3137  input.selectAll();
3138  builderRename.setView(input);
3139  builderRename.setPositiveButton("OK", new DialogInterface.OnClickListener() {
3140  @Override
3141  public void onClick(DialogInterface dialog, int which)
3142  {
3143  final String fileName = input.getText().toString();
3144  dialog.dismiss();
3145  if(!fileName.isEmpty())
3146  {
3147  File newFile = new File(mWorkingDirectory + fileName + ".db");
3148  if(newFile.exists())
3149  {
3150  AlertDialog d2 = new AlertDialog.Builder(getActivity())
3151  .setCancelable(false)
3152  .setTitle("File Already Exists")
3153  .setMessage(String.format("Name %s already used, choose another name.", fileName))
3154  .create();
3155  d2.setCanceledOnTouchOutside(false);
3156  d2.show();
3157  }
3158  else
3159  {
3160  File from = new File(mWorkingDirectory, files[position]);
3161  File to = new File(mWorkingDirectory, fileName + ".db");
3162  from.renameTo(to);
3163 
3164  long stamp = System.currentTimeMillis();
3165  if(stamp-mSavedStamp < 10000)
3166  {
3167  try {
3168  Thread.sleep(10000 - (stamp-mSavedStamp));
3169  }
3170  catch(InterruptedException e){}
3171  }
3172 
3173  refreshSystemMediaScanDataBase(getActivity(), files[position]);
3174  refreshSystemMediaScanDataBase(getActivity(), to.getAbsolutePath());
3175 
3176  ad.dismiss();
3177  resetNoTouchTimer(true);
3178  }
3179  }
3180  }
3181  });
3182  AlertDialog alertToShow = builderRename.create();
3183  alertToShow.setCanceledOnTouchOutside(false);
3184  alertToShow.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
3185  alertToShow.show();
3186  return true;
3187  }
3188  });
3189  menu.add(Menu.NONE, 1, 1, "Delete").setOnMenuItemClickListener(new OnMenuItemClickListener() {
3190  @Override
3191  public boolean onMenuItemClick(MenuItem item) {
3192  DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
3193  @Override
3194  public void onClick(DialogInterface dialog, int which) {
3195  switch (which){
3196  case DialogInterface.BUTTON_POSITIVE:
3197  Log.e(TAG, String.format("Yes delete %s!", files[position]));
3198  (new File(mWorkingDirectory+files[position])).delete();
3199  refreshSystemMediaScanDataBase(getActivity(), mWorkingDirectory+files[position]);
3200  ad.dismiss();
3201  resetNoTouchTimer(true);
3202  break;
3203 
3204  case DialogInterface.BUTTON_NEGATIVE:
3205  //No button clicked
3206  break;
3207  }
3208  }
3209  };
3210  AlertDialog dialog = new AlertDialog.Builder(getActivity())
3211  .setCancelable(false)
3212  .setTitle(String.format("Delete %s", files[position]))
3213  .setMessage("Are you sure?")
3214  .setPositiveButton("Yes", dialogClickListener)
3215  .setNegativeButton("No", dialogClickListener).create();
3216  dialog.setCanceledOnTouchOutside(false);
3217  dialog.show();
3218  return true;
3219  }
3220  });
3221  menu.add(Menu.NONE, 2, 2, "Share").setOnMenuItemClickListener(new OnMenuItemClickListener() {
3222  @Override
3223  public boolean onMenuItemClick(MenuItem item) {
3224 
3225  if (!PermissionHelper.hasPermission(getActivity(), Manifest.permission.INTERNET)) {
3226  PermissionHelper.requestPermission(getActivity(), Manifest.permission.INTERNET);
3227  return false;
3228  }
3229 
3230  // Send to...
3231  File f = new File(mWorkingDirectory+files[position]);
3232  final int fileSizeMB = (int)f.length()/(1024 * 1024);
3233  Intent shareIntent = new Intent();
3234  shareIntent.setAction(Intent.ACTION_SEND);
3235  shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
3236  Uri fileUri = FileProvider.getUriForFile(getActivity(), getActivity().getApplicationContext().getPackageName() + ".provider", f);
3237  shareIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
3238  shareIntent.setType("application/octet-stream");
3239  startActivity(Intent.createChooser(shareIntent, String.format("Sharing database \"%s\" (%d MB)...", files[position], fileSizeMB)));
3240  ad.dismiss();
3241  resetNoTouchTimer(true);
3242  return true;
3243  }
3244  });
3245  }
3246  }
3247  });
3248  }
3249  });
3250  ad.show();
3251  }
3252  }
3253 
3254  private void export(final boolean isOBJ, final boolean meshing, final boolean regenerateCloud, final boolean optimized, final int optimizedMaxPolygons)
3255  {
3256  final String extension = isOBJ? ".obj" : ".ply";
3257 
3258  // get Export settings
3259  SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
3260  final String cloudVoxelSizeStr = sharedPref.getString(getString(R.string.pref_key_cloud_voxel), getString(R.string.pref_default_cloud_voxel));
3261  final float cloudVoxelSize = Float.parseFloat(cloudVoxelSizeStr);
3262  final int textureSize = isOBJ?Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_texture_size), getString(R.string.pref_default_texture_size))):0;
3263  final int textureCount = Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_texture_count), getString(R.string.pref_default_texture_count)));
3264  final int normalK = Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_normal_k), getString(R.string.pref_default_normal_k)));
3265  final float maxTextureDistance = Float.parseFloat(sharedPref.getString(getString(R.string.pref_key_max_texture_distance), getString(R.string.pref_default_max_texture_distance)));
3266  final int minTextureClusterSize = Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_min_texture_cluster_size), getString(R.string.pref_default_min_texture_cluster_size)));
3267  final float optimizedVoxelSize = cloudVoxelSize;
3268  final int optimizedDepth = Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_opt_depth), getString(R.string.pref_default_opt_depth)));
3269  final float optimizedColorRadius = Float.parseFloat(sharedPref.getString(getString(R.string.pref_key_opt_color_radius), getString(R.string.pref_default_opt_color_radius)));
3270  final boolean optimizedCleanWhitePolygons = sharedPref.getBoolean(getString(R.string.pref_key_opt_clean_white), Boolean.parseBoolean(getString(R.string.pref_default_opt_clean_white)));
3271  final int optimizedMinClusterSize = Integer.parseInt(sharedPref.getString(getString(R.string.pref_key_opt_min_cluster_size), getString(R.string.pref_default_opt_min_cluster_size)));
3272  final boolean blockRendering = sharedPref.getBoolean(getString(R.string.pref_key_block_render), Boolean.parseBoolean(getString(R.string.pref_default_block_render)));
3273 
3274 
3275  mExportProgressDialog.setTitle("Exporting");
3276  mExportProgressDialog.setMessage(String.format("Please wait while preparing data to export..."));
3277  mExportProgressDialog.setProgress(0);
3278 
3279  final State previousState = mState;
3280 
3281  mExportProgressDialog.show();
3282  updateState(State.STATE_PROCESSING);
3283 
3284  Thread exportThread = new Thread(new Runnable() {
3285  public void run() {
3286 
3287  final long startTime = System.currentTimeMillis()/1000;
3288 
3289  final boolean success = RTABMapLib.exportMesh(
3290  nativeApplication,
3291  cloudVoxelSize,
3292  regenerateCloud,
3293  meshing,
3294  textureSize,
3295  textureCount,
3296  normalK,
3297  optimized,
3298  optimizedVoxelSize,
3299  optimizedDepth,
3300  optimizedMaxPolygons,
3301  optimizedColorRadius,
3302  optimizedCleanWhitePolygons,
3303  optimizedMinClusterSize,
3304  maxTextureDistance,
3305  minTextureClusterSize,
3306  blockRendering);
3307  runOnUiThread(new Runnable() {
3308  public void run() {
3309  if(mExportProgressDialog.isShowing())
3310  {
3311  if(success)
3312  {
3313  if(!meshing && cloudVoxelSize>0.0f)
3314  {
3315  mToast.makeText(getActivity(), String.format("Cloud assembled and voxelized at %s m.", cloudVoxelSizeStr), mToast.LENGTH_LONG).show();
3316  }
3317 
3318  final long endTime = System.currentTimeMillis()/1000;
3319 
3320  if(endTime-startTime > 10)
3321  {
3322  // build notification
3323  // the addAction re-use the same intent to keep the example short
3324  SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
3325  boolean notifySound = sharedPref.getBoolean(getString(R.string.pref_key_notification_sound), Boolean.parseBoolean(getString(R.string.pref_default_notification_sound)));
3326  Notification n = new Notification.Builder(getActivity())
3327  .setContentTitle(getString(R.string.app_name))
3328  .setContentText("Data generated and ready to be exported!")
3329  .setSmallIcon(R.drawable.ic_launcher)
3330  .setDefaults(notifySound?Notification.DEFAULT_SOUND:0)
3331  .setAutoCancel(true).build();
3332 
3333  NotificationManager notificationManager =
3334  (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
3335 
3336  notificationManager.notify(0, n);
3337  }
3338 
3339  // Visualize the result
3340  resetNoTouchTimer(true);
3341  mSavedRenderingType = mItemRenderingPointCloud.isChecked()?0:mItemRenderingMesh.isChecked()?1:2;
3342  if(!meshing)
3343  {
3344  mItemRenderingPointCloud.setChecked(true);
3345  }
3346  else if(!isOBJ)
3347  {
3348  mItemRenderingMesh.setChecked(true);
3349  }
3350  else // isOBJ
3351  {
3352  mItemRenderingTextureMesh.setChecked(true);
3353  }
3354  if(!optimizedCleanWhitePolygons)
3355  {
3356  mButtonLighting.setChecked(true);
3357  RTABMapLib.setLighting(nativeApplication, true);
3358  }
3359  updateState(State.STATE_VISUALIZING);
3360  RTABMapLib.postExportation(nativeApplication, true);
3361  if(mButtonCameraView.getSelectedItemPosition() == 0)
3362  {
3363  setCamera(2);
3364  }
3365  if(mOpenedDatabasePath.isEmpty())
3366  {
3367  save();
3368  }
3369  }
3370  else
3371  {
3372  updateState(previousState);
3373  mToast.makeText(getActivity(), String.format("Exporting map failed!"), mToast.LENGTH_LONG).show();
3374  }
3375  mExportProgressDialog.dismiss();
3376  }
3377  else
3378  {
3379  mProgressDialog.dismiss();
3380  mToast.makeText(getActivity(), String.format("Export canceled"), mToast.LENGTH_LONG).show();
3381  updateState(previousState);
3382  }
3383  }
3384  });
3385  }
3386  });
3387  exportThread.start();
3388  }
3389 
3390  public void save()
3391  {
3392  AlertDialog.Builder builder = new AlertDialog.Builder(this);
3393  builder.setCancelable(false);
3394  builder.setTitle("RTAB-Map Database Name (*.db):");
3395  final EditText input = new EditText(this);
3396  input.setInputType(InputType.TYPE_CLASS_TEXT);
3397  if(mOpenedDatabasePath.isEmpty())
3398  {
3399  String timeStamp = new SimpleDateFormat("yyMMdd-HHmmss").format(mDateOnPause);
3400  input.setText(timeStamp);
3401  }
3402  else
3403  {
3404  File f = new File(mOpenedDatabasePath);
3405  String name = f.getName();
3406  input.setText(name.substring(0,name.lastIndexOf(".")));
3407  }
3408  input.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
3409  input.setSelectAllOnFocus(true);
3410  input.selectAll();
3411  builder.setView(input);
3412  builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
3413  @Override
3414  public void onClick(DialogInterface dialog, int which)
3415  {
3416  //do nothing
3417  }
3418  });
3419  builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
3420  @Override
3421  public void onClick(DialogInterface dialog, int which)
3422  {
3423  final String fileName = input.getText().toString();
3424  dialog.dismiss();
3425  if(!fileName.isEmpty())
3426  {
3427  File newFile = new File(mWorkingDirectory + fileName + ".db");
3428  if(newFile.exists())
3429  {
3430  AlertDialog d2 = new AlertDialog.Builder(getActivity())
3431  .setCancelable(false)
3432  .setTitle("File Already Exists")
3433  .setMessage("Do you want to overwrite the existing file?")
3434  .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
3435  public void onClick(DialogInterface dialog, int which) {
3436  saveDatabase(fileName);
3437  }
3438  })
3439  .setNegativeButton("No", new DialogInterface.OnClickListener() {
3440  public void onClick(DialogInterface dialog, int which) {
3441  dialog.dismiss();
3442  resetNoTouchTimer(true);
3443  }
3444  })
3445  .create();
3446  d2.setCanceledOnTouchOutside(false);
3447  d2.show();
3448  }
3449  else
3450  {
3451  saveDatabase(fileName);
3452  }
3453  }
3454  }
3455  });
3456  AlertDialog alertToShow = builder.create();
3457  alertToShow.setCanceledOnTouchOutside(false);
3458  alertToShow.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
3459  alertToShow.show();
3460  }
3461 
3467  public static void refreshSystemMediaScanDataBase(Context context, String docPath){
3468  Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
3469  Uri contentUri = Uri.fromFile(new File(docPath));
3470  mediaScanIntent.setData(contentUri);
3471  context.sendBroadcast(mediaScanIntent);
3472  }
3473 
3474  private void saveDatabase(final String fileName)
3475  {
3476  final String newDatabasePath = mWorkingDirectory + fileName + ".db";
3477  final String newDatabasePathHuman = mWorkingDirectoryHuman + fileName + ".db";
3478  mProgressDialog.setTitle("Saving");
3479  if(mOpenedDatabasePath.equals(newDatabasePath))
3480  {
3481  mProgressDialog.setMessage(String.format("Please wait while updating \"%s\"...", newDatabasePathHuman));
3482  }
3483  else
3484  {
3485  mProgressDialog.setMessage(String.format("Please wait while saving \"%s\"...", newDatabasePathHuman));
3486  }
3487  mProgressDialog.show();
3488  final State previousState = mState;
3489  updateState(State.STATE_PROCESSING);
3490  Thread saveThread = new Thread(new Runnable() {
3491  public void run() {
3492  RTABMapLib.save(nativeApplication, newDatabasePath); // save
3493  runOnUiThread(new Runnable() {
3494  public void run() {
3495  String msg;
3496  if(mOpenedDatabasePath.equals(newDatabasePath))
3497  {
3498  msg = String.format("Database \"%s\" updated.", newDatabasePathHuman);
3499  }
3500  else
3501  {
3502  refreshSystemMediaScanDataBase(getActivity(), newDatabasePath);
3503  mSavedStamp = System.currentTimeMillis();
3504  msg = String.format("Database saved to \"%s\".", newDatabasePathHuman);
3505  }
3506 
3507  // build notification
3508  Intent intent = new Intent(getActivity(), RTABMapActivity.class);
3509  // use System.currentTimeMillis() to have a unique ID for the pending intent
3510  PendingIntent pIntent = PendingIntent.getActivity(getActivity(), (int) System.currentTimeMillis(), intent, 0);
3511  SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
3512  boolean notifySound = sharedPref.getBoolean(getString(R.string.pref_key_notification_sound), Boolean.parseBoolean(getString(R.string.pref_default_notification_sound)));
3513  Notification n = new Notification.Builder(getActivity())
3514  .setContentTitle(getString(R.string.app_name))
3515  .setContentText(msg)
3516  .setSmallIcon(R.drawable.ic_launcher)
3517  .setContentIntent(pIntent)
3518  .setDefaults(notifySound?Notification.DEFAULT_SOUND:0)
3519  .setAutoCancel(true).build();
3520 
3521  NotificationManager notificationManager =
3522  (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
3523 
3524  notificationManager.notify(0, n);
3525 
3526  final File f = new File(newDatabasePath);
3527  final int fileSizeMB = (int)f.length()/(1024 * 1024);
3528 
3529  if(!mItemDataRecorderMode.isChecked())
3530  {
3531  mOpenedDatabasePath = newDatabasePath;
3532  }
3533  mProgressDialog.dismiss();
3534  updateState(previousState);
3535 
3536  AlertDialog d2 = new AlertDialog.Builder(getActivity())
3537  .setCancelable(false)
3538  .setTitle("Database saved!")
3539  .setMessage(String.format("Database \"%s\" (%d MB) successfully saved!", newDatabasePathHuman, fileSizeMB))
3540  .setPositiveButton("OK", new DialogInterface.OnClickListener() {
3541  public void onClick(DialogInterface dialog, int which) {
3542  resetNoTouchTimer(true);
3543  }
3544  })
3545  .create();
3546  d2.setCanceledOnTouchOutside(true);
3547  d2.show();
3548  }
3549  });
3550  }
3551  });
3552  saveThread.start();
3553  }
3554 
3555  private void saveOnDevice()
3556  {
3557  AlertDialog.Builder builder = new AlertDialog.Builder(this);
3558  builder.setTitle("Model Name:");
3559  final EditText input = new EditText(this);
3560  input.setInputType(InputType.TYPE_CLASS_TEXT);
3561  builder.setView(input);
3562  if(mOpenedDatabasePath.isEmpty())
3563  {
3564  String timeStamp = new SimpleDateFormat("yyMMdd-HHmmss").format(mDateOnPause);
3565  input.setText(timeStamp);
3566  }
3567  else
3568  {
3569  File f = new File(mOpenedDatabasePath);
3570  String name = f.getName();
3571  input.setText(name.substring(0,name.lastIndexOf(".")));
3572  }
3573  input.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
3574  input.setSelectAllOnFocus(true);
3575  input.selectAll();
3576  builder.setCancelable(false);
3577  builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
3578  @Override
3579  public void onClick(DialogInterface dialog, int which)
3580  {
3581  dialog.dismiss();
3582  resetNoTouchTimer(true);
3583  }
3584  });
3585  builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
3586  @Override
3587  public void onClick(DialogInterface dialog, int which)
3588  {
3589  final String fileName = input.getText().toString();
3590  dialog.dismiss();
3591  if(!fileName.isEmpty())
3592  {
3593  writeExportedFiles(fileName);
3594  }
3595  }
3596  });
3597  AlertDialog alertToShow = builder.create();
3598  alertToShow.setCanceledOnTouchOutside(false);
3599  alertToShow.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
3600  alertToShow.show();
3601  }
3602 
3603  private void writeExportedFiles(final String fileName)
3604  {
3605  Log.i(TAG, String.format("Write exported mesh to \"%s\"", fileName));
3606 
3607  mProgressDialog.setTitle("Exporting");
3608  mProgressDialog.setMessage(String.format("Compressing the files..."));
3609  mProgressDialog.show();
3610 
3611  Thread workingThread = new Thread(new Runnable() {
3612  public void run() {
3613  boolean success = false;
3614 
3615  File tmpDir = new File(mWorkingDirectory + RTABMAP_TMP_DIR);
3616  tmpDir.mkdirs();
3617  String[] fileNames = Util.loadFileList(mWorkingDirectory + RTABMAP_TMP_DIR, false);
3618  if(!DISABLE_LOG) Log.i(TAG, String.format("Deleting %d files in \"%s\"", fileNames.length, mWorkingDirectory + RTABMAP_TMP_DIR));
3619  for(int i=0; i<fileNames.length; ++i)
3620  {
3621  File f = new File(mWorkingDirectory + RTABMAP_TMP_DIR + "/" + fileNames[i]);
3622  if(f.delete())
3623  {
3624  if(!DISABLE_LOG) Log.i(TAG, String.format("Deleted \"%s\"", f.getPath()));
3625  }
3626  else
3627  {
3628  if(!DISABLE_LOG) Log.i(TAG, String.format("Failed deleting \"%s\"", f.getPath()));
3629  }
3630  }
3631  File exportDir = new File(mWorkingDirectory + RTABMAP_EXPORT_DIR);
3632  exportDir.mkdirs();
3633 
3634  final String pathHuman = mWorkingDirectoryHuman + RTABMAP_EXPORT_DIR + fileName + ".zip";
3635  final String zipOutput = mWorkingDirectory+RTABMAP_EXPORT_DIR+fileName+".zip";
3636  if(RTABMapLib.writeExportedMesh(nativeApplication, mWorkingDirectory + RTABMAP_TMP_DIR, RTABMAP_TMP_FILENAME))
3637  {
3638  fileNames = Util.loadFileList(mWorkingDirectory + RTABMAP_TMP_DIR, false);
3639  if(fileNames.length > 0)
3640  {
3641  String[] filesToZip = new String[fileNames.length];
3642  for(int i=0; i<fileNames.length; ++i)
3643  {
3644  filesToZip[i] = mWorkingDirectory + RTABMAP_TMP_DIR + "/" + fileNames[i];
3645  }
3646 
3647  File toZIPFile = new File(zipOutput);
3648  toZIPFile.delete();
3649 
3650  try
3651  {
3652  Util.zip(filesToZip, zipOutput);
3653  success = true;
3654  }
3655  catch(IOException e)
3656  {
3657  final String msg = e.getMessage();
3658  runOnUiThread(new Runnable() {
3659  public void run() {
3660  mToast.makeText(getActivity(), String.format("Exporting mesh \"%s\" failed! Error=%s", fileName, msg), mToast.LENGTH_LONG).show();
3661  }
3662  });
3663  }
3664  }
3665  }
3666 
3667  if(success)
3668  {
3669  runOnUiThread(new Runnable() {
3670  public void run() {
3671  mProgressDialog.dismiss();
3672 
3673  final File f = new File(zipOutput);
3674  final int fileSizeMB = (int)f.length()/(1024 * 1024);
3675 
3676  AlertDialog d = new AlertDialog.Builder(getActivity())
3677  .setCancelable(false)
3678  .setTitle("Mesh Saved!")
3679  .setMessage(String.format("Mesh \"%s\" (%d MB) successfully exported! Share it?", pathHuman, fileSizeMB))
3680  .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
3681  public void onClick(DialogInterface dialog, int which) {
3682  // Send to...
3683  Intent shareIntent = new Intent();
3684  shareIntent.setAction(Intent.ACTION_SEND);
3685  shareIntent.putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(getActivity(), getActivity().getApplicationContext().getPackageName() + ".provider", f));
3686  shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
3687  shareIntent.setType("application/zip");
3688  startActivity(Intent.createChooser(shareIntent, "Sharing..."));
3689 
3690  resetNoTouchTimer(true);
3691  }
3692  })
3693  .setNegativeButton("No", new DialogInterface.OnClickListener() {
3694  public void onClick(DialogInterface dialog, int which) {
3695  resetNoTouchTimer(true);
3696  }
3697  }).create();
3698  d.setCanceledOnTouchOutside(false);
3699  d.show();
3700  }
3701  });
3702  }
3703  else
3704  {
3705  runOnUiThread(new Runnable() {
3706  public void run() {
3707  mProgressDialog.dismiss();
3708  mToast.makeText(getActivity(), String.format("Exporting mesh \"%s\" failed! No files found in tmp directory!? Last export may have failed or have been canceled.", fileName), mToast.LENGTH_LONG).show();
3709  resetNoTouchTimer(true);
3710  }
3711  });
3712  }
3713  }
3714  });
3715  workingThread.start();
3716  }
3717 
3718  private void openDatabase(final String fileName, final boolean optimize)
3719  {
3720  mOpenedDatabasePath = mWorkingDirectory + fileName;
3721 
3722  Log.i(TAG, "Open database " + mOpenedDatabasePath);
3723 
3724  SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
3725  final boolean databaseInMemory = sharedPref.getBoolean(getString(R.string.pref_key_db_in_memory), Boolean.parseBoolean(getString(R.string.pref_default_db_in_memory)));
3726 
3727  mProgressDialog.setTitle("Loading");
3728  mProgressDialog.setMessage(String.format("Opening database \"%s\"...", fileName));
3729  mProgressDialog.show();
3730  updateState(State.STATE_PROCESSING);
3731 
3732  Thread openThread = new Thread(new Runnable() {
3733  public void run() {
3734 
3735  final int status = RTABMapLib.openDatabase(nativeApplication, mOpenedDatabasePath, databaseInMemory, optimize, false);
3736 
3737  runOnUiThread(new Runnable() {
3738  public void run() {
3739  if(status == -1)
3740  {
3741  updateState(State.STATE_IDLE);
3742  mProgressDialog.dismiss();
3743  AlertDialog d = new AlertDialog.Builder(getActivity())
3744  .setCancelable(false)
3745  .setTitle("Error")
3746  .setMessage("The map is loaded but optimization of the map's graph has "
3747  + "failed, so the map cannot be shown. Change the Graph Optimizer approach used"
3748  + " or enable/disable if the graph is optimized from graph "
3749  + "end in \"Settings -> Mapping...\" and try opening again.")
3750  .setPositiveButton("Open Settings", new DialogInterface.OnClickListener() {
3751  public void onClick(DialogInterface dialog, int which) {
3752  Intent intent = new Intent(getActivity(), SettingsActivity.class);
3753  startActivity(intent);
3754  }
3755  })
3756  .setNegativeButton("Close", new DialogInterface.OnClickListener() {
3757  public void onClick(DialogInterface dialog, int which) {
3758  }
3759  }).create();
3760  d.setCanceledOnTouchOutside(false);
3761  d.show();
3762  }
3763  else if(status == -2)
3764  {
3765  updateState(State.STATE_IDLE);
3766  mProgressDialog.dismiss();
3767  AlertDialog d = new AlertDialog.Builder(getActivity())
3768  .setCancelable(false)
3769  .setTitle("Error")
3770  .setMessage("Failed to open database: Out of memory! Try "
3771  + "again after lowering Point Cloud Density in Settings.")
3772  .setPositiveButton("Open Settings", new DialogInterface.OnClickListener() {
3773  public void onClick(DialogInterface dialog, int which) {
3774  Intent intent = new Intent(getActivity(), SettingsActivity.class);
3775  startActivity(intent);
3776  }
3777  })
3778  .setNegativeButton("Close", new DialogInterface.OnClickListener() {
3779  public void onClick(DialogInterface dialog, int which) {
3780  }
3781  }).create();
3782  d.setCanceledOnTouchOutside(false);
3783  d.show();
3784  }
3785  else
3786  {
3787  if(status >= 1 && status<=3)
3788  {
3789  mProgressDialog.dismiss();
3790  resetNoTouchTimer(true);
3791  updateState(State.STATE_VISUALIZING);
3792  mToast.makeText(getActivity(), String.format("Database loaded!"), mToast.LENGTH_LONG).show();
3793  }
3794  else if(!mItemTrajectoryMode.isChecked())
3795  {
3796  if(mButtonCameraView.getSelectedItemPosition() == 0)
3797  {
3798  setCamera(2);
3799  }
3800  // creating meshes...
3801  updateState(State.STATE_IDLE);
3802  mProgressDialog.setTitle("Loading");
3803  mProgressDialog.setMessage(String.format("Database \"%s\" loaded. Please wait while rendering point clouds and meshes...", fileName));
3804  }
3805 
3806  }
3807  }
3808  });
3809  }
3810  });
3811  openThread.start();
3812  }
3813 
3814  private void shareToSketchfab()
3815  {
3816  if (!PermissionHelper.hasPermission(this, Manifest.permission.INTERNET)) {
3817  PermissionHelper.requestPermission(this, Manifest.permission.INTERNET);
3818  return;
3819  }
3820 
3821  Intent intent = new Intent(getActivity(), SketchfabActivity.class);
3822 
3823  intent.putExtra(RTABMAP_AUTH_TOKEN_KEY, mAuthToken);
3824  intent.putExtra(RTABMAP_WORKING_DIR_KEY, mWorkingDirectory);
3825 
3826  if(mOpenedDatabasePath.isEmpty())
3827  {
3828  intent.putExtra(RTABMAP_FILENAME_KEY, new SimpleDateFormat("yyMMdd-HHmmss").format(mDateOnPause));
3829  }
3830  else
3831  {
3832  File f = new File(mOpenedDatabasePath);
3833  String name = f.getName();
3834  intent.putExtra(RTABMAP_FILENAME_KEY, name.substring(0,name.lastIndexOf(".")));
3835  }
3836 
3837  startActivityForResult(intent, SKETCHFAB_ACTIVITY_CODE);
3838  }
3839 }
com.introlab.rtabmap.RTABMapActivity.getActionBarHeight
int getActionBarHeight()
Definition: RTABMapActivity.java:941
com.introlab.rtabmap.RTABMapActivity.mStatusTexts
String[] mStatusTexts
Definition: RTABMapActivity.java:260
com.introlab.rtabmap.RTABMapActivity.TAG
static final String TAG
Definition: RTABMapActivity.java:113
com.introlab.rtabmap.RTABMapLib.postProcessing
static native int postProcessing(long nativeApplication, int approach)
com.introlab.rtabmap.RTABMapLib.setOnlineBlending
static native void setOnlineBlending(long nativeApplication, boolean enabled)
int
int
create
ADT create(const Signature &signature)
com.introlab.rtabmap.PermissionHelper.CAMERA_CODE
static final int CAMERA_CODE
Definition: PermissionHelper.java:29
com.introlab.rtabmap.RTABMapActivity.updatePreferences
void updatePreferences()
Definition: RTABMapActivity.java:1074
com.introlab.rtabmap.RTABMapActivity.mLastEnvSensorsSet
boolean[] mLastEnvSensorsSet
Definition: RTABMapActivity.java:238
com.introlab.rtabmap.RTABMapActivity.mDateOnPause
Date mDateOnPause
Definition: RTABMapActivity.java:174
com.introlab.rtabmap.RTABMapActivity.mItemOpen
MenuItem mItemOpen
Definition: RTABMapActivity.java:179
com.introlab.rtabmap.RTABMapLib.setOrthoCropFactor
static native void setOrthoCropFactor(long nativeApplication, float value)
com.introlab.rtabmap.RTABMapLib.setTrajectoryMode
static native void setTrajectoryMode(long nativeApplication, boolean enabled)
com.introlab.rtabmap.RTABMapLib.setLighting
static native void setLighting(long nativeApplication, boolean enabled)
com.introlab.rtabmap.RTABMapActivity.mOnPause
boolean mOnPause
Definition: RTABMapActivity.java:173
com.introlab.rtabmap.RTABMapActivity.onClick
void onClick(View v)
Definition: RTABMapActivity.java:1464
com.introlab.rtabmap.RTABMapLib.createNativeApplication
static native long createNativeApplication(RTABMapActivity activity)
save
save
com.introlab.rtabmap.RTABMapLib.setMeshTriangleSize
static native void setMeshTriangleSize(long nativeApplication, int value)
com.introlab.rtabmap.RTABMapActivity.setCamera
void setCamera(int type)
Definition: RTABMapActivity.java:1442
com.introlab.rtabmap.RTABMapLib.setGridVisible
static native void setGridVisible(long nativeApplication, boolean visible)
name
com.introlab.rtabmap.PermissionHelper.WRITE_EXTERNAL_STORAGE_CODE
static final int WRITE_EXTERNAL_STORAGE_CODE
Definition: PermissionHelper.java:31
glm::length
GLM_FUNC_DECL genType::value_type length(genType const &x)
com.introlab.rtabmap.RTABMapActivity.mItemLocalizationMode
MenuItem mItemLocalizationMode
Definition: RTABMapActivity.java:186
com.introlab.rtabmap.RTABMapActivity.updateCameraDriverSettings
void updateCameraDriverSettings()
Definition: RTABMapActivity.java:748
glm::yaw
GLM_FUNC_DECL T yaw(detail::tquat< T, P > const &x)
run
void run(class_loader::ClassLoader *loader)
format
std::string format(const std::string &str, const std::vector< std::string > &find, const std::vector< std::string > &replace)
com.introlab.rtabmap.RTABMapActivity.mButtonWireframe
ToggleButton mButtonWireframe
Definition: RTABMapActivity.java:199
com.introlab.rtabmap.TangoInitializationHelper
Definition: TangoInitializationHelper.java:34
com.introlab.rtabmap.RTABMapActivity.startMapping
void startMapping()
Definition: RTABMapActivity.java:2385
com.introlab.rtabmap.RTABMapActivity.mWifiManager
WifiManager mWifiManager
Definition: RTABMapActivity.java:228
timer
com.introlab.rtabmap.RTABMapActivity.mLastAccelerometerSet
boolean mLastAccelerometerSet
Definition: RTABMapActivity.java:242
com.introlab.rtabmap.RTABMapActivity.shareToSketchfab
void shareToSketchfab()
Definition: RTABMapActivity.java:3814
com.introlab.rtabmap.RTABMapActivity.save
void save()
Definition: RTABMapActivity.java:3390
com.introlab.rtabmap.Renderer.updateTexts
void updateTexts(String[] texts)
Definition: Renderer.java:234
com.introlab.rtabmap.RTABMapActivity.mAuthToken
String mAuthToken
Definition: RTABMapActivity.java:136
com.introlab.rtabmap.RTABMapActivity.mRenderer
Renderer mRenderer
Definition: RTABMapActivity.java:159
com.introlab.rtabmap.RTABMapActivity.mLastMagnetometer
float[] mLastMagnetometer
Definition: RTABMapActivity.java:241
com.introlab.rtabmap.RTABMapActivity.mOnPauseStamp
long mOnPauseStamp
Definition: RTABMapActivity.java:172
com.introlab.rtabmap.RTABMapActivity.onActivityResult
void onActivityResult(int requestCode, int resultCode, Intent data)
Definition: RTABMapActivity.java:985
com.introlab.rtabmap.RTABMapActivity.mItemRenderingTextureMesh
MenuItem mItemRenderingTextureMesh
Definition: RTABMapActivity.java:190
com.introlab.rtabmap.RTABMapActivity.mSeekBarGrid
SeekBar mSeekBarGrid
Definition: RTABMapActivity.java:207
str::format
str format(Args &&...args) const
com.introlab.rtabmap.RTABMapActivity.resetNoTouchTimer
void resetNoTouchTimer(boolean showHud)
Definition: RTABMapActivity.java:2218
com.introlab.rtabmap.RTABMapLib.setBackfaceCulling
static native void setBackfaceCulling(long nativeApplication, boolean enabled)
com.introlab.rtabmap.RTABMapLib.setCamera
static native void setCamera(long nativeApplication, int cameraIndex)
com.introlab.rtabmap.Util.loadFileList
static String[] loadFileList(final String directory, final boolean databasesOnly)
Definition: Util.java:62
com.introlab.rtabmap.RTABMapActivity.TANGO_PACKAGE_NAME
static final String TANGO_PACKAGE_NAME
Definition: RTABMapActivity.java:120
com.introlab.rtabmap.RTABMapActivity.EXTRA_VALUE_ADF
static final String EXTRA_VALUE_ADF
Definition: RTABMapActivity.java:123
com.introlab.rtabmap.RTABMapActivity.onAccuracyChanged
void onAccuracyChanged(Sensor sensor, int accuracy)
Definition: RTABMapActivity.java:928
gtsam::Symbol::equals
bool equals(const Symbol &expected, double tol=0.0) const
com.introlab.rtabmap.RTABMapLib.setMinCloudDepth
static native void setMinCloudDepth(long nativeApplication, float value)
com.introlab.rtabmap.RTABMapActivity.mItemExport
MenuItem mItemExport
Definition: RTABMapActivity.java:182
com.introlab.rtabmap.RTABMapActivity.onItemSelected
void onItemSelected(AdapterView<?> parent, View view, int pos, long id)
Definition: RTABMapActivity.java:1530
count
Index count
com.introlab.rtabmap.RTABMapLib.setMappingParameter
static native int setMappingParameter(long nativeApplication, String key, String value)
com.introlab.rtabmap.RTABMapActivity.mHudVisible
boolean mHudVisible
Definition: RTABMapActivity.java:139
com.introlab.rtabmap.RTABMapActivity.saveOnDevice
void saveOnDevice()
Definition: RTABMapActivity.java:3555
com.introlab.rtabmap.RTABMapActivity.mTimeThr
String mTimeThr
Definition: RTABMapActivity.java:214
com.introlab.rtabmap.RTABMapLib.setAppendMode
static native void setAppendMode(long nativeApplication, boolean enabled)
com.introlab.rtabmap.RTABMapActivity.mLastFastMovementNotificationStamp
long mLastFastMovementNotificationStamp
Definition: RTABMapActivity.java:175
com.introlab.rtabmap.RTABMapActivity.State.STATE_VISUALIZING_CAMERA
STATE_VISUALIZING_CAMERA
Definition: RTABMapActivity.java:152
com.introlab.rtabmap.Util.zip
static void zip(String file, String zipFile)
Definition: Util.java:27
type
com.introlab.rtabmap.RTABMapLib.setLocalizationMode
static native void setLocalizationMode(long nativeApplication, boolean enabled)
com.introlab.rtabmap.Renderer
Definition: Renderer.java:36
state
RecoveryProgressState state
Definition: tools/Recovery/main.cpp:56
com.introlab.rtabmap.RTABMapActivity.onDestroy
void onDestroy()
Definition: RTABMapActivity.java:866
com.introlab.rtabmap.RTABMapLib.setNodesFiltering
static native void setNodesFiltering(long nativeApplication, boolean enabled)
com.introlab.rtabmap.RTABMapLib.setMaxCloudDepth
static native void setMaxCloudDepth(long nativeApplication, float value)
com.introlab.rtabmap.RTABMapActivity.onMenuOpened
boolean onMenuOpened(int featureId, Menu menu)
Definition: RTABMapActivity.java:1002
com.introlab.rtabmap.NDSpinner.setSelection
void setSelection(int position, boolean animate)
Definition: NDSpinner.java:24
com.introlab.rtabmap.PermissionHelper.shouldShowRequestPermissionRationale
static boolean shouldShowRequestPermissionRationale(Activity activity, String permission)
Definition: PermissionHelper.java:68
y
Matrix3f y
com.introlab.rtabmap.RTABMapActivity.closeVisualization
void closeVisualization()
Definition: RTABMapActivity.java:1513
com.introlab.rtabmap.RTABMapActivity.updateProgressionUI
void updateProgressionUI(int count, int max)
Definition: RTABMapActivity.java:2023
com.introlab.rtabmap.Renderer.setProgressDialog
void setProgressDialog(ProgressDialog progressDialog)
Definition: Renderer.java:63
com.introlab.rtabmap.RTABMapActivity.mLastAccelerometer
float[] mLastAccelerometer
Definition: RTABMapActivity.java:240
com.introlab.rtabmap.RTABMapActivity.stopMapping
void stopMapping()
Definition: RTABMapActivity.java:2476
com.introlab.rtabmap.RTABMapLib.setGridRotation
static native void setGridRotation(long nativeApplication, float value)
com.introlab.rtabmap.RTABMapActivity.mItemResume
MenuItem mItemResume
Definition: RTABMapActivity.java:185
com.introlab.rtabmap.RTABMapActivity.RTABMAP_TMP_FILENAME
static final String RTABMAP_TMP_FILENAME
Definition: RTABMapActivity.java:127
com.introlab.rtabmap.RTABMapActivity.rtabmapInitEventCallback
void rtabmapInitEventCallback(final int status, final String msg)
Definition: RTABMapActivity.java:2010
com.introlab.rtabmap.RTABMapActivity.mItemDebugVisibility
MenuItem mItemDebugVisibility
Definition: RTABMapActivity.java:193
com.introlab.rtabmap.RTABMapActivity.mItemPostProcessing
MenuItem mItemPostProcessing
Definition: RTABMapActivity.java:181
com.introlab.rtabmap.RTABMapLib.writeExportedMesh
static native boolean writeExportedMesh(long nativeApplication, String directory, String name)
com.introlab.rtabmap.RTABMapActivity.onNothingSelected
void onNothingSelected(AdapterView<?> parent)
Definition: RTABMapActivity.java:1535
com.introlab.rtabmap.RTABMapActivity.mButtonCameraView
NDSpinner mButtonCameraView
Definition: RTABMapActivity.java:195
com.introlab.rtabmap.RTABMapActivity.onWindowFocusChanged
void onWindowFocusChanged(boolean hasFocus)
Definition: RTABMapActivity.java:953
com.introlab.rtabmap.RTABMapActivity.mButtonLighting
ToggleButton mButtonLighting
Definition: RTABMapActivity.java:198
com.introlab.rtabmap.RTABMapLib.addEnvSensor
static native void addEnvSensor(long nativeApplication, int type, float value)
com.introlab.rtabmap.RTABMapActivity.mItemModes
MenuItem mItemModes
Definition: RTABMapActivity.java:184
com.introlab.rtabmap.RTABMapActivity.mWorkingDirectoryHuman
String mWorkingDirectoryHuman
Definition: RTABMapActivity.java:211
com.introlab.rtabmap.RTABMapActivity.mItemRenderingPointCloud
MenuItem mItemRenderingPointCloud
Definition: RTABMapActivity.java:188
com.introlab.rtabmap.Renderer.setToast
void setToast(Toast toast)
Definition: Renderer.java:68
com.introlab.rtabmap.RTABMapLib.stopCamera
static native void stopCamera(long nativeApplication)
com.introlab.rtabmap.RTABMapActivity.openDatabase
void openDatabase()
Definition: RTABMapActivity.java:3050
com.introlab.rtabmap.RTABMapActivity.SKETCHFAB_ACTIVITY_CODE
static final int SKETCHFAB_ACTIVITY_CODE
Definition: RTABMapActivity.java:135
com.introlab.rtabmap.RTABMapActivity.mGPSSaved
boolean mGPSSaved
Definition: RTABMapActivity.java:219
com.introlab.rtabmap.RTABMapActivity.mBackClickedTime
Date mBackClickedTime
Definition: RTABMapActivity.java:171
com.introlab.rtabmap.RTABMapActivity.mMinInliers
String mMinInliers
Definition: RTABMapActivity.java:217
com.introlab.rtabmap.RTABMapActivity.mLocationManager
LocationManager mLocationManager
Definition: RTABMapActivity.java:224
com.introlab.rtabmap.RTABMapActivity.mButtonCloseVisualization
Button mButtonCloseVisualization
Definition: RTABMapActivity.java:201
optimize
gtsam.ISAM2 optimize(List[GpsMeasurement] gps_measurements, List[ImuMeasurement] imu_measurements, gtsam.noiseModel.Diagonal sigma_init_x, gtsam.noiseModel.Diagonal sigma_init_v, gtsam.noiseModel.Diagonal sigma_init_b, gtsam.noiseModel.Diagonal noise_model_gps, KittiCalibration kitti_calibration, int first_gps_pose, int gps_skip)
com.introlab.rtabmap.RTABMapActivity.mOpenedDatabasePath
String mOpenedDatabasePath
Definition: RTABMapActivity.java:209
n
int n
com.introlab.rtabmap.RTABMapActivity.postCreate
void postCreate()
Definition: RTABMapActivity.java:737
com.introlab.rtabmap.RTABMapActivity.onPanelClosed
void onPanelClosed(int featureId, Menu menu)
Definition: RTABMapActivity.java:1008
com.introlab.rtabmap.RTABMapActivity.onOptionsItemSelected
boolean onOptionsItemSelected(MenuItem item)
Definition: RTABMapActivity.java:2558
Matrix
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > Matrix
matches
matches
com.introlab.rtabmap.RTABMapActivity.copy
void copy(Uri uri, File file)
Definition: RTABMapActivity.java:694
com.introlab.rtabmap.RTABMapActivity.mCompassDeg
float mCompassDeg
Definition: RTABMapActivity.java:236
com.introlab.rtabmap.RTABMapActivity.onBackPressed
void onBackPressed()
Definition: RTABMapActivity.java:1013
com.introlab.rtabmap.RTABMapLib.setRenderingTextureDecimation
static native void setRenderingTextureDecimation(long nativeApplication, int value)
com.introlab.rtabmap.DatabaseListArrayAdapter
Definition: DatabaseListArrayAdapter.java:23
com.introlab.rtabmap.RTABMapActivity.mMaxFeatures
String mMaxFeatures
Definition: RTABMapActivity.java:215
com.introlab.rtabmap.RTABMapLib
Definition: RTABMapLib.java:15
com.introlab.rtabmap.RTABMapActivity.startCamera
void startCamera(final String message)
Definition: RTABMapActivity.java:1305
com.introlab.rtabmap.RTABMapActivity.State.STATE_VISUALIZING_WHILE_LOADING
STATE_VISUALIZING_WHILE_LOADING
Definition: RTABMapActivity.java:153
com.introlab.rtabmap.RTABMapActivity.mButtonNewScan
Button mButtonNewScan
Definition: RTABMapActivity.java:205
com.introlab.rtabmap.ARCoreSharedCamera.setToast
void setToast(Toast toast)
Definition: ARCoreSharedCamera.java:122
app
QApplication * app
Definition: tools/DataRecorder/main.cpp:59
com.introlab.rtabmap.RTABMapActivity.RTABMAP_TMP_DIR
static final String RTABMAP_TMP_DIR
Definition: RTABMapActivity.java:126
data
int data[]
com.introlab.rtabmap.RTABMapLib.onTouchEvent
static native void onTouchEvent(long nativeApplication, int touchCount, int event0, float x0, float y0, float x1, float y1)
com.introlab.rtabmap.RTABMapActivity.mLastEnvSensors
float[] mLastEnvSensors
Definition: RTABMapActivity.java:237
com.introlab.rtabmap.RTABMapLib.setSmoothing
static native void setSmoothing(long nativeApplication, boolean enabled)
com.introlab.rtabmap.RTABMapActivity.updateState
void updateState(State state)
Definition: RTABMapActivity.java:2244
com.introlab.rtabmap.RTABMapActivity.mButtonShareOnSketchfab
Button mButtonShareOnSketchfab
Definition: RTABMapActivity.java:203
Float
FloatingPoint< float > Float
com.introlab.rtabmap.RTABMapActivity.mFreeMemoryOnStart
long mFreeMemoryOnStart
Definition: RTABMapActivity.java:176
com.introlab.rtabmap.RTABMapActivity.mItemNewScan
MenuItem mItemNewScan
Definition: RTABMapActivity.java:180
com.introlab.rtabmap.RTABMapActivity.mButtonBackfaceShown
ToggleButton mButtonBackfaceShown
Definition: RTABMapActivity.java:200
com.introlab.rtabmap.RTABMapActivity.STATUS_TEXTS_SIZE
final int STATUS_TEXTS_SIZE
Definition: RTABMapActivity.java:258
com.introlab.rtabmap.RTABMapActivity.mLocationListener
LocationListener mLocationListener
Definition: RTABMapActivity.java:225
com.introlab.rtabmap.PermissionHelper.INTERNET_CODE
static final int INTERNET_CODE
Definition: PermissionHelper.java:32
com.introlab.rtabmap.Renderer.setCamera
void setCamera(ARCoreSharedCamera camera)
Definition: Renderer.java:78
com.introlab.rtabmap.RTABMapActivity.State.STATE_CAMERA
STATE_CAMERA
Definition: RTABMapActivity.java:147
com.introlab.rtabmap.RTABMapLib.setCloudDensityLevel
static native void setCloudDensityLevel(long nativeApplication, int value)
com.introlab.rtabmap.RTABMapActivity.mButtonStart
ImageButton mButtonStart
Definition: RTABMapActivity.java:196
com.introlab.rtabmap.RTABMapActivity.RTABMAP_WORKING_DIR_KEY
static final String RTABMAP_WORKING_DIR_KEY
Definition: RTABMapActivity.java:134
com.introlab.rtabmap.Renderer.setOffset
void setOffset(int offset)
Definition: Renderer.java:73
glm::pi
GLM_FUNC_DECL genType pi()
com.introlab.rtabmap.Util
Definition: Util.java:23
com.introlab.rtabmap.RTABMapActivity.writeExportedFiles
void writeExportedFiles(final String fileName)
Definition: RTABMapActivity.java:3603
com.introlab.rtabmap.RTABMapActivity.setNavVisibility
void setNavVisibility(boolean visible)
Definition: RTABMapActivity.java:964
com.introlab.rtabmap.RTABMapActivity.State
Definition: RTABMapActivity.java:145
com.introlab.rtabmap.RTABMapActivity.DISABLE_LOG
static boolean DISABLE_LOG
Definition: RTABMapActivity.java:114
com.introlab.rtabmap.TangoInitializationHelper.bindTangoService
static final boolean bindTangoService(final Context context, ServiceConnection connection)
Definition: TangoInitializationHelper.java:50
com.introlab.rtabmap.RTABMapActivity.mEnvSensorsTimer
Timer mEnvSensorsTimer
Definition: RTABMapActivity.java:229
com.introlab.rtabmap.RTABMapActivity.getStatusBarHeight
int getStatusBarHeight()
Definition: RTABMapActivity.java:933
glm::max
GLM_FUNC_DECL genType max(genType const &x, genType const &y)
com.introlab.rtabmap.RTABMapActivity.State.STATE_MAPPING
STATE_MAPPING
Definition: RTABMapActivity.java:148
com.introlab.rtabmap.RTABMapLib.setMeshRendering
static native void setMeshRendering(long nativeApplication, boolean enabled, boolean withTexture)
com.introlab.rtabmap.RTABMapActivity.cameraEventCallback
void cameraEventCallback(final int type, final String key, final String value)
Definition: RTABMapActivity.java:2113
com.introlab.rtabmap.RTABMapActivity.onPause
void onPause()
Definition: RTABMapActivity.java:1045
com.introlab.rtabmap.ARCoreSharedCamera.openCamera
boolean openCamera()
Definition: ARCoreSharedCamera.java:349
com.introlab.rtabmap.RTABMapLib.setRawScanSaved
static native void setRawScanSaved(long nativeApplication, boolean enabled)
com.introlab.rtabmap.ARCoreSharedCamera.close
void close()
Definition: ARCoreSharedCamera.java:616
com.introlab.rtabmap.RTABMapActivity.openDatabase
void openDatabase(final String fileName, final boolean optimize)
Definition: RTABMapActivity.java:3718
com.introlab.rtabmap.RTABMapLib.exportMesh
static native boolean exportMesh(long nativeApplication, float cloudVoxelSize, boolean regenerateCloud, boolean meshing, int textureSize, int textureCount, int normalK, boolean optimized, float optimizedVoxelSize, int optimizedDepth, int optimizedMaxPolygons, float optimizedColorRadius, boolean optimizedCleanWhitePolygons, int optimizedMinClusterSize, float optimizedMaxTextureDistance, int optimizedMinTextureClusterSize, boolean blockRendering)
com.introlab.rtabmap.RTABMapActivity.mItemSave
MenuItem mItemSave
Definition: RTABMapActivity.java:178
com.introlab.rtabmap.RTABMapActivity.mMemoryWarningDialog
AlertDialog mMemoryWarningDialog
Definition: RTABMapActivity.java:256
com.introlab.rtabmap.RTABMapActivity.updateStatusTexts
void updateStatusTexts()
Definition: RTABMapActivity.java:1652
info
else if n * info
com.introlab.rtabmap.RTABMapLib.setMeshAngleTolerance
static native void setMeshAngleTolerance(long nativeApplication, float value)
com.introlab.rtabmap.RTABMapActivity.getFileName
String getFileName(Uri uri)
Definition: RTABMapActivity.java:713
com.introlab.rtabmap.RTABMapActivity.mItemDataRecorderMode
MenuItem mItemDataRecorderMode
Definition: RTABMapActivity.java:191
L
MatrixXd L
Boolean
unsigned char Boolean
Definition: ConvertUTF.h:93
d
d
com.introlab.rtabmap.PermissionHelper
Definition: PermissionHelper.java:28
params
SmartProjectionParams params(gtsam::HESSIAN, gtsam::ZERO_ON_DEGENERACY)
com.introlab.rtabmap.PermissionHelper.hasPermission
static boolean hasPermission(Activity activity, String permission)
Definition: PermissionHelper.java:38
z
z
com.introlab.rtabmap.RTABMapActivity.updateStatsCallback
void updateStatsCallback(final int nodes, final int words, final int points, final int polygons, final float updateTime, final int loopClosureId, final int highestHypId, final int databaseMemoryUsed, final int inliers, final int matches, final int featuresExtracted, final float hypothesis, final int nodesDrawn, final float fps, final int rejected, final float rehearsalValue, final float optimizationMaxError, final float optimizationMaxErrorRatio, final float distanceTravelled, final int fastMovement, final int landmarkDetected, final float x, final float y, final float z, final float roll, final float pitch, final float yaw)
Definition: RTABMapActivity.java:1826
x
x
com.introlab.rtabmap.RTABMapActivity.newScan
void newScan()
Definition: RTABMapActivity.java:2915
com.introlab.rtabmap.RTABMapActivity.onSensorChanged
void onSensorChanged(SensorEvent event)
Definition: RTABMapActivity.java:878
com.introlab.rtabmap.RTABMapActivity.State.STATE_IDLE
STATE_IDLE
Definition: RTABMapActivity.java:149
com.introlab.rtabmap.RTABMapActivity.mItemSettings
MenuItem mItemSettings
Definition: RTABMapActivity.java:183
com.introlab.rtabmap.PermissionHelper.launchPermissionSettings
static void launchPermissionSettings(Activity activity)
Definition: PermissionHelper.java:73
com.introlab.rtabmap.RTABMapActivity.nativeApplication
static long nativeApplication
Definition: RTABMapActivity.java:110
com.introlab.rtabmap.RTABMapActivity.isArEngineAvailable
void isArEngineAvailable()
Definition: RTABMapActivity.java:835
com.introlab.rtabmap.RTABMapActivity.State.STATE_PROCESSING
STATE_PROCESSING
Definition: RTABMapActivity.java:150
action
action
com.introlab.rtabmap.RTABMapLib.isBuiltWith
static native boolean isBuiltWith(long nativeApplication, int cameraDriver)
glm::pitch
GLM_FUNC_DECL T pitch(detail::tquat< T, P > const &x)
com.introlab.rtabmap.RTABMapActivity.mSeekBarOrthoCut
SeekBar mSeekBarOrthoCut
Definition: RTABMapActivity.java:206
out
std::ofstream out("Result.txt")
com.introlab.rtabmap.RTABMapLib.recover
static native boolean recover(long nativeApplication, String from, String to)
com.introlab.rtabmap.RTABMapActivity.saveDatabase
void saveDatabase(final String fileName)
Definition: RTABMapActivity.java:3474
com.introlab.rtabmap.RTABMapLib.postExportation
static native boolean postExportation(long nativeApplication, boolean visualize)
com.introlab.rtabmap.RTABMapActivity.mButtonLibrary
Button mButtonLibrary
Definition: RTABMapActivity.java:204
str
key
const gtsam::Symbol key( 'X', 0)
f
Point2(* f)(const Point3 &, OptionalJacobian< 2, 3 >)
d2
d2
com.introlab.rtabmap.RTABMapLib.setGraphOptimization
static native void setGraphOptimization(long nativeApplication, boolean enabled)
nodes
KeyVector nodes
com.introlab.rtabmap.RTABMapActivity.mButtonSaveOnDevice
Button mButtonSaveOnDevice
Definition: RTABMapActivity.java:202
e
Array< double, 1, 3 > e(1./3., 0.5, 2.)
com.introlab.rtabmap.RTABMapActivity.rtabmapInitEventUI
void rtabmapInitEventUI(int status, String msg)
Definition: RTABMapActivity.java:1952
com.introlab.rtabmap.RTABMapActivity.CheckTangoCoreVersion
boolean CheckTangoCoreVersion(int minVersion)
Definition: RTABMapActivity.java:2125
com.introlab.rtabmap.RTABMapActivity.mMaxOptimizationError
String mMaxOptimizationError
Definition: RTABMapActivity.java:218
com.introlab.rtabmap.RTABMapActivity.standardOptimization
void standardOptimization(final boolean withStandardMeshExport)
Definition: RTABMapActivity.java:2140
State
com.introlab.rtabmap.RTABMapLib.setMapCloudShown
static native void setMapCloudShown(long nativeApplication, boolean shown)
com.introlab.rtabmap.RTABMapActivity.resumeScan
void resumeScan()
Definition: RTABMapActivity.java:2908
com.introlab.rtabmap.RTABMapActivity.mIntentDbToOpen
String mIntentDbToOpen
Definition: RTABMapActivity.java:267
com.introlab.rtabmap.RTABMapActivity.mLastMagnetometerSet
boolean mLastMagnetometerSet
Definition: RTABMapActivity.java:243
com.introlab.rtabmap.RTABMapActivity.mMenuOpened
boolean mMenuOpened
Definition: RTABMapActivity.java:141
com.introlab.rtabmap.RTABMapLib.setCameraColor
static native void setCameraColor(long nativeApplication, boolean enabled)
com.introlab.rtabmap.RTABMapActivity.EXTRA_KEY_PERMISSIONTYPE
static final String EXTRA_KEY_PERMISSIONTYPE
Definition: RTABMapActivity.java:122
com.introlab.rtabmap.RTABMapActivity.mGLView
GLSurfaceView mGLView
Definition: RTABMapActivity.java:160
com.introlab.rtabmap.RTABMapActivity.mUpdateRate
String mUpdateRate
Definition: RTABMapActivity.java:213
com.introlab.rtabmap.RTABMapActivity.RTABMAP_AUTH_TOKEN_KEY
static final String RTABMAP_AUTH_TOKEN_KEY
Definition: RTABMapActivity.java:131
values
leaf::MyValues values
com.introlab.rtabmap.RTABMapActivity.State.STATE_WELCOME
STATE_WELCOME
Definition: RTABMapActivity.java:146
com.introlab.rtabmap.RTABMapActivity.getActivity
RTABMapActivity getActivity()
Definition: RTABMapActivity.java:2138
com.introlab.rtabmap.RTABMapActivity.onRequestPermissionsResult
void onRequestPermissionsResult(int requestCode, String[] permissions, int[] results)
Definition: RTABMapActivity.java:1258
com.introlab.rtabmap.RTABMapActivity.mSavedStamp
long mSavedStamp
Definition: RTABMapActivity.java:142
com.introlab.rtabmap.RTABMapActivity.mItemTrajectoryMode
MenuItem mItemTrajectoryMode
Definition: RTABMapActivity.java:187
com.introlab.rtabmap.RTABMapLib.setOdomCloudShown
static native void setOdomCloudShown(long nativeApplication, boolean shown)
com.introlab.rtabmap.RTABMapActivity.mSensorManager
SensorManager mSensorManager
Definition: RTABMapActivity.java:227
com.introlab.rtabmap.RTABMapActivity.mItemStatusVisibility
MenuItem mItemStatusVisibility
Definition: RTABMapActivity.java:192
com.introlab.rtabmap.RTABMapLib.setScreenRotation
static native void setScreenRotation(long nativeApplication, int displayRotation, int cameraRotation)
com.introlab.rtabmap.RTABMapLib.startCamera
static native boolean startCamera(long nativeApplication, IBinder binder, Context context, Activity activity, int driver)
com.introlab.rtabmap.RTABMapActivity.RTABMAP_EXPORT_DIR
static final String RTABMAP_EXPORT_DIR
Definition: RTABMapActivity.java:129
com.introlab.rtabmap.RTABMapLib.setBackgroundColor
static native void setBackgroundColor(long nativeApplication, float gray)
com.introlab.rtabmap.RTABMapActivity.export
void export(final boolean isOBJ, final boolean meshing, final boolean regenerateCloud, final boolean optimized, final int optimizedMaxPolygons)
Definition: RTABMapActivity.java:3254
timeStamp
ros::Time const * timeStamp(const M &m)
com.introlab.rtabmap.RTABMapActivity.RTABMAP_OPENED_DB_PATH_KEY
static final String RTABMAP_OPENED_DB_PATH_KEY
Definition: RTABMapActivity.java:133
com.introlab.rtabmap.PermissionHelper.requestPermission
static void requestPermission(Activity activity, String permission)
Definition: PermissionHelper.java:43
com.introlab.rtabmap.RTABMapLib.setPointSize
static native void setPointSize(long nativeApplication, float value)
com.introlab.rtabmap.RTABMapActivity.NOTOUCH_TIMEOUT
static final long NOTOUCH_TIMEOUT
Definition: RTABMapActivity.java:138
com.introlab.rtabmap.RTABMapActivity.mToast
Toast mToast
Definition: RTABMapActivity.java:254
com
com.introlab.rtabmap.RTABMapActivity.onCreate
void onCreate(Bundle savedInstanceState)
Definition: RTABMapActivity.java:314
v
Array< int, Dynamic, 1 > v
position
Point3 position(const NavState &X, OptionalJacobian< 3, 9 > H)
com.introlab.rtabmap.RTABMapActivity.setAndroidOrientation
void setAndroidOrientation()
Definition: RTABMapActivity.java:1539
com.introlab.rtabmap.RTABMapActivity.resetNoTouchTimer
void resetNoTouchTimer()
Definition: RTABMapActivity.java:2214
com.introlab.rtabmap.RTABMapActivity.onResume
void onResume()
Definition: RTABMapActivity.java:1222
com.introlab.rtabmap.RTABMapLib.save
static native void save(long nativeApplication, String outputDatabasePath)
Camera
PinholePose< Cal3_S2 > Camera
com.introlab.rtabmap.RTABMapActivity.State.STATE_VISUALIZING
STATE_VISUALIZING
Definition: RTABMapActivity.java:151
com.introlab.rtabmap.RTABMapActivity.RTABMAP_TMP_DB
static final String RTABMAP_TMP_DB
Definition: RTABMapActivity.java:125
com.introlab.rtabmap.RTABMapActivity.mScreenSize
Point mScreenSize
Definition: RTABMapActivity.java:170
com.introlab.rtabmap.ARCoreSharedCamera
Definition: ARCoreSharedCamera.java:49
results
std::map< std::string, Array< float, 1, 8, DontAlign|RowMajor > > results
com.introlab.rtabmap.RTABMapActivity.refreshSystemMediaScanDataBase
static void refreshSystemMediaScanDataBase(Context context, String docPath)
Definition: RTABMapActivity.java:3467
com.introlab.rtabmap.RTABMapActivity.updateProgressionCallback
void updateProgressionCallback(final int count, final int max)
Definition: RTABMapActivity.java:2034
com.introlab.rtabmap.RTABMapActivity.onCreateOptionsMenu
boolean onCreateOptionsMenu(Menu menu)
Definition: RTABMapActivity.java:1575
com.introlab.rtabmap.RTABMapActivity.RTABMAP_FILENAME_KEY
static final String RTABMAP_FILENAME_KEY
Definition: RTABMapActivity.java:132
com.introlab.rtabmap.RTABMapActivity.mEnvSensorsSaved
boolean mEnvSensorsSaved
Definition: RTABMapActivity.java:220
float
float
com.introlab.rtabmap.ARCoreSharedCamera.isDepthSupported
boolean isDepthSupported()
Definition: ARCoreSharedCamera.java:120
com.introlab.rtabmap.NDSpinner
Definition: NDSpinner.java:12
com.introlab.rtabmap.SketchfabActivity
Definition: SketchfabActivity.java:36
com.introlab.rtabmap.RTABMapActivity.MIN_TANGO_CORE_VERSION
static final int MIN_TANGO_CORE_VERSION
Definition: RTABMapActivity.java:117
com.introlab.rtabmap.RTABMapActivity.stopCamera
void stopCamera()
Definition: RTABMapActivity.java:2421
len
size_t len(handle h)
com.introlab.rtabmap.RTABMapActivity.mNewR
Matrix mNewR
Definition: RTABMapActivity.java:247
com.introlab.rtabmap.RTABMapLib.setFullResolution
static native void setFullResolution(long nativeApplication, boolean enabled)
com.introlab.rtabmap.RTABMapLib.setWireframe
static native void setWireframe(long nativeApplication, boolean enabled)
com.introlab.rtabmap.RTABMapLib.setGraphVisible
static native void setGraphVisible(long nativeApplication, boolean visible)
com.introlab.rtabmap.RTABMapLib.setClusterRatio
static native void setClusterRatio(long nativeApplication, float value)
com.introlab.rtabmap.RTABMapActivity.mTotalLoopClosures
int mTotalLoopClosures
Definition: RTABMapActivity.java:251
com.introlab.rtabmap.RTABMapActivity.RTABMAP_SDCARD_PATH
static final String RTABMAP_SDCARD_PATH
Definition: RTABMapActivity.java:128
com.introlab.rtabmap.RTABMapActivity.cameraEventUI
void cameraEventUI(int type, String key, String value)
Definition: RTABMapActivity.java:2047
com.introlab.rtabmap.RTABMapActivity.mItemRenderingMesh
MenuItem mItemRenderingMesh
Definition: RTABMapActivity.java:189
com.introlab.rtabmap.RTABMapLib.setDepthFromMotion
static native void setDepthFromMotion(long nativeApplication, boolean enabled)
pos
com.introlab.rtabmap.RTABMapLib.openDatabase
static native int openDatabase(long nativeApplication, String databasePath, boolean databaseInMemory, boolean optimize, boolean clearDatabase)
com.introlab.rtabmap.RTABMapLib.setMaxGainRadius
static native void setMaxGainRadius(long nativeApplication, float value)
com.introlab.rtabmap.RTABMapLib.destroyNativeApplication
static native void destroyNativeApplication(long nativeApplication)
t
Point2 t(10, 10)
com.introlab.rtabmap.RTABMapActivity.mWorkingDirectory
String mWorkingDirectory
Definition: RTABMapActivity.java:210
com.introlab.rtabmap.RTABMapActivity.mButtonStop
ImageButton mButtonStop
Definition: RTABMapActivity.java:197
dst
char * dst
Definition: lz4.h:354
com.introlab.rtabmap.RTABMapActivity.mLastKnownLocation
Location mLastKnownLocation
Definition: RTABMapActivity.java:226
com.introlab.rtabmap.RTABMapActivity.mSavedRenderingType
int mSavedRenderingType
Definition: RTABMapActivity.java:140
com.introlab.rtabmap.RTABMapActivity.updateStatsUI
void updateStatsUI(int loopClosureId, int inliers, int matches, int rejected, float optimizationMaxError, float optimizationMaxErrorRatio, boolean fastMovement, int landmarkDetected, String[] statusTexts)
Definition: RTABMapActivity.java:1683
com.introlab.rtabmap.RTABMapActivity.stopDisconnectTimer
void stopDisconnectTimer()
Definition: RTABMapActivity.java:2238
com.introlab.rtabmap.SettingsActivity
Definition: SettingsActivity.java:27
com.introlab.rtabmap.Renderer.setTextColor
void setTextColor(float color)
Definition: Renderer.java:264
com.introlab.rtabmap.RTABMapActivity.mDeviceToCamera
Matrix mDeviceToCamera
Definition: RTABMapActivity.java:245
file
file
com.introlab.rtabmap.RTABMapActivity.mIsARCoreAvailable
boolean mIsARCoreAvailable
Definition: RTABMapActivity.java:221
com.introlab.rtabmap.RTABMapActivity.mIsAREngineAvailable
boolean mIsAREngineAvailable
Definition: RTABMapActivity.java:222
value
value
com.introlab.rtabmap.RTABMapActivity.copy
void copy(File src, File dst)
Definition: RTABMapActivity.java:680
openDatabase
static int openDatabase(const char *zFilename, sqlite3 **ppDb, unsigned int flags, const char *zVfs)
Definition: sqlite3.c:121402
com.introlab.rtabmap.RTABMapActivity.mR
float[] mR
Definition: RTABMapActivity.java:248
com.introlab.rtabmap.RTABMapActivity.getFreeMemory
long getFreeMemory()
Definition: RTABMapActivity.java:1644
i
int i
com.introlab.rtabmap.RTABMapLib.setUpstreamRelocalizationAccThr
static native void setUpstreamRelocalizationAccThr(long nativeApplication, float value)
com.introlab.rtabmap.RTABMapActivity.STATUS_TEXTS_POSE_INDEX
final int STATUS_TEXTS_POSE_INDEX
Definition: RTABMapActivity.java:259
result
RESULT & result
com.introlab.rtabmap.RTABMapActivity.mLoopThr
String mLoopThr
Definition: RTABMapActivity.java:216
com.introlab.rtabmap.RTABMapActivity.mRMat
Matrix mRMat
Definition: RTABMapActivity.java:246
glm::roll
GLM_FUNC_DECL T roll(detail::tquat< T, P > const &x)
com.introlab.rtabmap.RTABMapLib.setPausedMapping
static native void setPausedMapping(long nativeApplication, boolean paused)
com.introlab.rtabmap.RTABMapActivity.mOrientation
float[] mOrientation
Definition: RTABMapActivity.java:249
msg
msg
com.introlab.rtabmap.RTABMapActivity.isArCoreAvailable
void isArCoreAvailable()
Definition: RTABMapActivity.java:813
R
R
com.introlab.rtabmap.RTABMapActivity
Definition: RTABMapActivity.java:107


rtabmap
Author(s): Mathieu Labbe
autogenerated on Sun Dec 1 2024 03:42:51