0.14: added gps field to Node table in database (#226). Tango: saving gps if enabled, added Rename/Remove/Share on long click in Open dialog (fixed #233)

This commit is contained in:
matlabbe
2017-09-21 20:59:45 -04:00
parent 114490f01e
commit bfc393a090
22 changed files with 516 additions and 103 deletions
+2 -2
View File
@@ -20,8 +20,8 @@ SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules")
# VERSION # VERSION
####################### #######################
SET(RTABMAP_MAJOR_VERSION 0) SET(RTABMAP_MAJOR_VERSION 0)
SET(RTABMAP_MINOR_VERSION 13) SET(RTABMAP_MINOR_VERSION 14)
SET(RTABMAP_PATCH_VERSION 3) SET(RTABMAP_PATCH_VERSION 0)
SET(RTABMAP_VERSION SET(RTABMAP_VERSION
${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION}) ${RTABMAP_MAJOR_VERSION}.${RTABMAP_MINOR_VERSION}.${RTABMAP_PATCH_VERSION})
+2
View File
@@ -12,6 +12,8 @@
<uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" /> <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-feature android:name="android.hardware.location.gps" />
<uses-feature android:glEsVersion="0x00020000" /> <uses-feature android:glEsVersion="0x00020000" />
<!-- This is the platform API where NativeActivity was introduced. --> <!-- This is the platform API where NativeActivity was introduced. -->
+28 -1
View File
@@ -116,7 +116,8 @@ CameraTango::CameraTango(bool colorCamera, int decimation, bool publishRawScan,
cloudStamp_(0), cloudStamp_(0),
tangoColorType_(0), tangoColorType_(0),
tangoColorStamp_(0), tangoColorStamp_(0),
colorCameraToDisplayRotation_(ROTATION_0) colorCameraToDisplayRotation_(ROTATION_0),
lastKnownGPS_(std::vector<double>(6,0))
{ {
UASSERT(decimation >= 1); UASSERT(decimation >= 1);
} }
@@ -189,6 +190,8 @@ bool CameraTango::init(const std::string & calibrationFolder, const std::string
{ {
close(); close();
lastKnownGPS_ = std::vector<double>(6,0);
TangoSupport_initialize(TangoService_getPoseAtTime, TangoService_getCameraIntrinsics); TangoSupport_initialize(TangoService_getPoseAtTime, TangoService_getCameraIntrinsics);
// Connect to Tango // Connect to Tango
@@ -513,6 +516,21 @@ std::string CameraTango::getSerial() const
return "Tango"; return "Tango";
} }
void CameraTango::setGPS(double stamp,
double longitude,
double latitude,
double altitude,
double accuracy,
double bearing)
{
lastKnownGPS_[0] = stamp;
lastKnownGPS_[1] = longitude;
lastKnownGPS_[2] = latitude;
lastKnownGPS_[3] = altitude;
lastKnownGPS_[4] = accuracy;
lastKnownGPS_[5] = bearing;
}
rtabmap::Transform CameraTango::tangoPoseToTransform(const TangoPoseData * tangoPose) const rtabmap::Transform CameraTango::tangoPoseToTransform(const TangoPoseData * tangoPose) const
{ {
UASSERT(tangoPose); UASSERT(tangoPose);
@@ -837,6 +855,15 @@ SensorData CameraTango::captureImage(CameraInfo * info)
data = SensorData(rgb, depth, model, this->getNextSeqID(), rgbStamp); data = SensorData(rgb, depth, model, this->getNextSeqID(), rgbStamp);
} }
data.setGroundTruth(odom); data.setGroundTruth(odom);
if(lastKnownGPS_[0] > 0.0 && rgbStamp-lastKnownGPS_[0]<2.0)
{
data.setGPS(lastKnownGPS_[0], lastKnownGPS_[1], lastKnownGPS_[2], lastKnownGPS_[3], lastKnownGPS_[4], lastKnownGPS_[5]);
}
else if(lastKnownGPS_[0]>0.0)
{
LOGD("GPS too old (current time=%f, gps time = %f)", rgbStamp, lastKnownGPS_[0]);
}
} }
else else
{ {
+7
View File
@@ -89,6 +89,12 @@ public:
void setSmoothing(bool enabled) {smoothing_ = enabled;} void setSmoothing(bool enabled) {smoothing_ = enabled;}
void setRawScanPublished(bool enabled) {rawScanPublished_ = enabled;} void setRawScanPublished(bool enabled) {rawScanPublished_ = enabled;}
void setScreenRotation(TangoSupportRotation colorCameraToDisplayRotation) {colorCameraToDisplayRotation_ = colorCameraToDisplayRotation;} void setScreenRotation(TangoSupportRotation colorCameraToDisplayRotation) {colorCameraToDisplayRotation_ = colorCameraToDisplayRotation;}
void setGPS(double stamp,
double longitude,
double latitude,
double altitude,
double accuracy,
double bearing);
void cloudReceived(const cv::Mat & cloud, double timestamp); void cloudReceived(const cv::Mat & cloud, double timestamp);
void rgbReceived(const cv::Mat & tangoImage, int type, double timestamp); void rgbReceived(const cv::Mat & tangoImage, int type, double timestamp);
@@ -126,6 +132,7 @@ private:
TangoSupportRotation colorCameraToDisplayRotation_; TangoSupportRotation colorCameraToDisplayRotation_;
cv::Mat fisheyeRectifyMapX_; cv::Mat fisheyeRectifyMapX_;
cv::Mat fisheyeRectifyMapY_; cv::Mat fisheyeRectifyMapY_;
std::vector<double> lastKnownGPS_;
}; };
} /* namespace rtabmap */ } /* namespace rtabmap */
+13
View File
@@ -1975,6 +1975,19 @@ int RTABMapApp::setMappingParameter(const std::string & key, const std::string &
} }
} }
void RTABMapApp::setGPS(double stamp,
double longitude,
double latitude,
double altitude,
double accuracy,
double bearing)
{
if(camera_)
{
camera_->setGPS(stamp, longitude, latitude, altitude, accuracy, bearing);
}
}
void RTABMapApp::resetMapping() void RTABMapApp::resetMapping()
{ {
LOGW("Reset!"); LOGW("Reset!");
+6
View File
@@ -147,6 +147,12 @@ class RTABMapApp : public UEventsHandler {
void setRenderingTextureDecimation(int value); void setRenderingTextureDecimation(int value);
void setBackgroundColor(float gray); void setBackgroundColor(float gray);
int setMappingParameter(const std::string & key, const std::string & value); int setMappingParameter(const std::string & key, const std::string & value);
void setGPS(double stamp,
double longitude,
double latitude,
double altitude,
double accuracy,
double bearing);
void resetMapping(); void resetMapping();
void save(const std::string & databasePath); void save(const std::string & databasePath);
+18
View File
@@ -339,6 +339,24 @@ Java_com_introlab_rtabmap_RTABMapLib_setMappingParameter(
return app.setMappingParameter(keyC, valueC); return app.setMappingParameter(keyC, valueC);
} }
JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_setGPS(
JNIEnv*, jobject,
double stamp,
double longitude,
double latitude,
double altitude,
double accuracy,
double bearing)
{
return app.setGPS(stamp,
longitude,
latitude,
altitude,
accuracy,
bearing);
}
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_com_introlab_rtabmap_RTABMapLib_resetMapping( Java_com_introlab_rtabmap_RTABMapLib_resetMapping(
JNIEnv*, jobject) JNIEnv*, jobject)
@@ -197,6 +197,11 @@
android:title="@string/pref_title_raw_scan_saved" android:title="@string/pref_title_raw_scan_saved"
android:summary="@string/pref_summary_raw_scan_saved" android:summary="@string/pref_summary_raw_scan_saved"
android:defaultValue="@string/pref_default_raw_scan_saved"/> android:defaultValue="@string/pref_default_raw_scan_saved"/>
<SwitchPreference
android:key="@string/pref_key_gps_saved"
android:title="@string/pref_title_gps_saved"
android:summary="@string/pref_summary_gps_saved"
android:defaultValue="@string/pref_default_gps_saved"/>
<SwitchPreference <SwitchPreference
android:key="@string/pref_key_db_in_memory" android:key="@string/pref_key_db_in_memory"
android:title="@string/pref_title_db_in_memory" android:title="@string/pref_title_db_in_memory"
+6
View File
@@ -34,6 +34,8 @@
<string name="memory">"Used Memory (MB): "</string> <string name="memory">"Used Memory (MB): "</string>
<string name="hypothesis">"Hypothesis (%): "</string> <string name="hypothesis">"Hypothesis (%): "</string>
<string name="fps">"FPS (rendering): "</string> <string name="fps">"FPS (rendering): "</string>
<string name="gps">"GPS (long,lat,alt,bearing,acc): "</string>
<string name="time">"Time: "</string>
<!-- Preference keys: BEGIN --> <!-- Preference keys: BEGIN -->
<string name="pref_key_tags">pref_key_tags</string> <string name="pref_key_tags">pref_key_tags</string>
@@ -101,6 +103,8 @@
<string name="pref_default_keep_all_db">true</string> <string name="pref_default_keep_all_db">true</string>
<string name="pref_key_raw_scan_saved">pref_key_raw_scan_saved</string> <string name="pref_key_raw_scan_saved">pref_key_raw_scan_saved</string>
<string name="pref_default_raw_scan_saved">false</string> <string name="pref_default_raw_scan_saved">false</string>
<string name="pref_key_gps_saved">pref_key_gps_saved</string>
<string name="pref_default_gps_saved">false</string>
<string name="pref_key_db_in_memory">pref_key_db_in_memory</string> <string name="pref_key_db_in_memory">pref_key_db_in_memory</string>
<string name="pref_default_db_in_memory">true</string> <string name="pref_default_db_in_memory">true</string>
@@ -339,6 +343,8 @@
<string name="pref_summary_keep_all_db">Discarded frames while not moving are still saved in database. Useful to replay exactly the scanning on RTAB-Map Desktop.</string> <string name="pref_summary_keep_all_db">Discarded frames while not moving are still saved in database. Useful to replay exactly the scanning on RTAB-Map Desktop.</string>
<string name="pref_title_raw_scan_saved">Save Raw Scan</string> <string name="pref_title_raw_scan_saved">Save Raw Scan</string>
<string name="pref_summary_raw_scan_saved">Save raw point clouds in database.</string> <string name="pref_summary_raw_scan_saved">Save raw point clouds in database.</string>
<string name="pref_title_gps_saved">Save GPS</string>
<string name="pref_summary_gps_saved">Save GPS in database.</string>
<string name="pref_title_db_in_memory">Database In Memory</string> <string name="pref_title_db_in_memory">Database In Memory</string>
<string name="pref_summary_db_in_memory">The database is kept in RAM for fast access. Set to false to reduce RAM used at the cost of slower access. This parameter is applied on reset or when a database is opened.</string> <string name="pref_summary_db_in_memory">The database is kept in RAM for fast access. Set to false to reduce RAM used at the cost of slower access. This parameter is applied on reset or when a database is opened.</string>
@@ -33,6 +33,7 @@ import android.app.ProgressDialog;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.DialogInterface.OnShowListener;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@@ -50,8 +51,15 @@ import android.graphics.Paint;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.hardware.Camera; import android.hardware.Camera;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.graphics.Point; import android.graphics.Point;
import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.Uri; import android.net.Uri;
@@ -74,15 +82,19 @@ import android.text.method.LinkMovementMethod;
import android.text.util.Linkify; import android.text.util.Linkify;
import android.util.Log; import android.util.Log;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.ContextMenu;
import android.view.Display; import android.view.Display;
import android.view.GestureDetector; import android.view.GestureDetector;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.Surface; import android.view.Surface;
import android.view.View; import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.View.OnCreateContextMenuListener;
import android.view.View.OnTouchListener; import android.view.View.OnTouchListener;
import android.view.Window; import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
@@ -90,11 +102,13 @@ import android.view.inputmethod.EditorInfo;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.AdapterView.OnItemSelectedListener; import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.NumberPicker; import android.widget.NumberPicker;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.SeekBar; import android.widget.SeekBar;
@@ -108,7 +122,7 @@ import com.google.atap.tangoservice.Tango;
// The main activity of the application. This activity shows debug information // The main activity of the application. This activity shows debug information
// and a glSurfaceView that renders graphic content. // and a glSurfaceView that renders graphic content.
public class RTABMapActivity extends Activity implements OnClickListener, OnItemSelectedListener { public class RTABMapActivity extends Activity implements OnClickListener, OnItemSelectedListener, SensorEventListener {
// Tag for debug logging. // Tag for debug logging.
public static final String TAG = RTABMapActivity.class.getSimpleName(); public static final String TAG = RTABMapActivity.class.getSimpleName();
@@ -206,6 +220,12 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
private String mLoopThr; private String mLoopThr;
private String mMinInliers; private String mMinInliers;
private String mMaxOptimizationError; private String mMaxOptimizationError;
private LocationManager mLocationManager;
private LocationListener mLocationListener;
private Location mLastKnownLocation;
private SensorManager mSensorManager;
private float mCompassDeg = 0.0f;
private int mTotalLoopClosures = 0; private int mTotalLoopClosures = 0;
private boolean mMapIsEmpty = false; private boolean mMapIsEmpty = false;
@@ -454,30 +474,69 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
RTABMapLib.openDatabase(tmpDatabase, databaseInMemory, false); RTABMapLib.openDatabase(tmpDatabase, databaseInMemory, false);
DisplayManager displayManager = (DisplayManager) getSystemService(DISPLAY_SERVICE); DisplayManager displayManager = (DisplayManager) getSystemService(DISPLAY_SERVICE);
if (displayManager != null) { if (displayManager != null) {
displayManager.registerDisplayListener(new DisplayManager.DisplayListener() { displayManager.registerDisplayListener(new DisplayManager.DisplayListener() {
@Override @Override
public void onDisplayAdded(int displayId) { public void onDisplayAdded(int displayId) {
} }
@Override @Override
public void onDisplayChanged(int displayId) { public void onDisplayChanged(int displayId) {
synchronized (this) { synchronized (this) {
setAndroidOrientation(); setAndroidOrientation();
Display display = getWindowManager().getDefaultDisplay(); Display display = getWindowManager().getDefaultDisplay();
display.getSize(mScreenSize); display.getSize(mScreenSize);
} }
} }
@Override @Override
public void onDisplayRemoved(int displayId) {} public void onDisplayRemoved(int displayId) {}
}, null); }, null);
} }
DISABLE_LOG = !( 0 != ( getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE ) ); // Acquire a reference to the system Location Manager
mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updates
mLocationListener = new LocationListener() {
public void onLocationChanged(Location location) {
mLastKnownLocation = location;
double stamp = location.getTime()/1000.0;
if(!DISABLE_LOG) Log.d(TAG, String.format("GPS received at %f (%d)", stamp, location.getTime()));
RTABMapLib.setGPS(
stamp,
(double)location.getLongitude(),
(double)location.getLatitude(),
(double)location.getAltitude(),
(double)location.getAccuracy(),
(double)mCompassDeg);
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
DISABLE_LOG = !( 0 != ( getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE ) );
} }
@Override
public void onSensorChanged(SensorEvent event) {
// get the angle around the z-axis rotated
mCompassDeg = event.values[0];
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// not in use
}
public int getStatusBarHeight() { public int getStatusBarHeight() {
int result = 0; int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
@@ -580,6 +639,10 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
if(!DISABLE_LOG) Log.i(TAG, "onPause()"); if(!DISABLE_LOG) Log.i(TAG, "onPause()");
mOnPause = true; mOnPause = true;
mLocationManager.removeUpdates(mLocationListener);
mSensorManager.unregisterListener(this);
// This deletes OpenGL context! // This deletes OpenGL context!
mGLView.onPause(); mGLView.onPause();
@@ -619,9 +682,8 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
} }
mProgressDialog.show(); mProgressDialog.show();
mOnPause = false; mOnPause = false;
setAndroidOrientation(); setAndroidOrientation();
// update preferences // update preferences
try try
{ {
@@ -640,6 +702,12 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
boolean keepAllDb = sharedPref.getBoolean(getString(R.string.pref_key_keep_all_db), Boolean.parseBoolean(getString(R.string.pref_default_keep_all_db))); boolean keepAllDb = sharedPref.getBoolean(getString(R.string.pref_key_keep_all_db), Boolean.parseBoolean(getString(R.string.pref_default_keep_all_db)));
boolean optimizeFromGraphEnd = sharedPref.getBoolean(getString(R.string.pref_key_optimize_end), Boolean.parseBoolean(getString(R.string.pref_default_optimize_end))); boolean optimizeFromGraphEnd = sharedPref.getBoolean(getString(R.string.pref_key_optimize_end), Boolean.parseBoolean(getString(R.string.pref_default_optimize_end)));
String optimizer = sharedPref.getString(getString(R.string.pref_key_optimizer), getString(R.string.pref_default_optimizer)); String optimizer = sharedPref.getString(getString(R.string.pref_key_optimizer), getString(R.string.pref_default_optimizer));
boolean gpsSaved = sharedPref.getBoolean(getString(R.string.pref_key_gps_saved), Boolean.parseBoolean(getString(R.string.pref_default_gps_saved)));
if(gpsSaved)
{
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListener);
mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_GAME);
}
if(!DISABLE_LOG) Log.d(TAG, "set mapping parameters"); if(!DISABLE_LOG) Log.d(TAG, "set mapping parameters");
RTABMapLib.setOnlineBlending(sharedPref.getBoolean(getString(R.string.pref_key_blending), Boolean.parseBoolean(getString(R.string.pref_default_blending)))); RTABMapLib.setOnlineBlending(sharedPref.getBoolean(getString(R.string.pref_key_blending), Boolean.parseBoolean(getString(R.string.pref_default_blending))));
@@ -1065,7 +1133,7 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
{ {
if(!DISABLE_LOG) Log.i(TAG, String.format("updateStatsCallback()")); if(!DISABLE_LOG) Log.i(TAG, String.format("updateStatsCallback()"));
final String[] statusTexts = new String[16]; final String[] statusTexts = new String[17];
if(mButtonPause!=null && !mButtonPause.isChecked()) if(mButtonPause!=null && !mButtonPause.isChecked())
{ {
String updateValue = mUpdateRate.compareTo("0")==0?"Max":mUpdateRate; String updateValue = mUpdateRate.compareTo("0")==0?"Max":mUpdateRate;
@@ -1101,8 +1169,7 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
statusTexts[1] = mStatusTexts[1]; statusTexts[1] = mStatusTexts[1];
} }
statusTexts[2] = getString(R.string.free_memory)+getFreeMemory(); statusTexts[2] = getString(R.string.free_memory)+getFreeMemory();
if(loopClosureId > 0) if(loopClosureId > 0)
{ {
++mTotalLoopClosures; ++mTotalLoopClosures;
@@ -1110,7 +1177,29 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
mMapNodes = nodes; mMapNodes = nodes;
int index = 4; if(mLastKnownLocation != null)
{
long millisec = System.currentTimeMillis() - mLastKnownLocation.getTime();
if(millisec > 2000)
{
statusTexts[3] = getString(R.string.gps)+String.format("[too old, %d ms]", millisec);
}
else
{
statusTexts[3] = getString(R.string.gps)+
String.format("%.2f %.2f %.2fm %.0fdeg %.0fm",
mLastKnownLocation.getLongitude(),
mLastKnownLocation.getLatitude(),
mLastKnownLocation.getAltitude(),
mCompassDeg,
mLastKnownLocation.getAccuracy());
}
}
String formattedDate = new SimpleDateFormat("HH:mm:ss.SSS").format(new Date());
statusTexts[4] = getString(R.string.time)+formattedDate;
int index = 5;
statusTexts[index++] = getString(R.string.nodes)+nodes+" (" + nodesDrawn + " shown)"; statusTexts[index++] = getString(R.string.nodes)+nodes+" (" + nodesDrawn + " shown)";
statusTexts[index++] = getString(R.string.words)+words; statusTexts[index++] = getString(R.string.words)+words;
statusTexts[index++] = getString(R.string.database_size)+databaseMemoryUsed; statusTexts[index++] = getString(R.string.database_size)+databaseMemoryUsed;
@@ -1123,7 +1212,7 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
statusTexts[index++] = getString(R.string.inliers)+inliers; statusTexts[index++] = getString(R.string.inliers)+inliers;
statusTexts[index++] = getString(R.string.hypothesis)+(int)(hypothesis*100.0f) +" / " + (int)(Float.parseFloat(mLoopThr)*100.0f) + " (" + (loopClosureId>0?loopClosureId:highestHypId)+")"; statusTexts[index++] = getString(R.string.hypothesis)+(int)(hypothesis*100.0f) +" / " + (int)(Float.parseFloat(mLoopThr)*100.0f) + " (" + (loopClosureId>0?loopClosureId:highestHypId)+")";
statusTexts[index++] = getString(R.string.fps)+(int)fps+" Hz"; statusTexts[index++] = getString(R.string.fps)+(int)fps+" Hz";
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
public void run() { public void run() {
updateStatsUI(adjustedMemoryUsed, loopClosureId, inliers, matches, rejected, optimizationMaxError, statusTexts); updateStatsUI(adjustedMemoryUsed, loopClosureId, inliers, matches, rejected, optimizationMaxError, statusTexts);
@@ -1489,7 +1578,7 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
mMapIsEmpty = false; mMapIsEmpty = false;
mDateOnPause = new Date(); mDateOnPause = new Date();
long memoryFree = getFreeMemory(); long memoryFree = getFreeMemory();
if(!mOnPause && !mItemLocalizationMode.isChecked() && !mItemDataRecorderMode.isChecked() && memoryFree >= 100 && mMapNodes>2) if(!mOnPause && !mItemLocalizationMode.isChecked() && !mItemDataRecorderMode.isChecked() && memoryFree >= 100 && mMapNodes>2)
{ {
@@ -1943,54 +2032,7 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
} }
else if(itemId == R.id.open) else if(itemId == R.id.open)
{ {
final String[] files = Util.loadFileList(mWorkingDirectory, true); openDatabase();
if(files.length > 0)
{
String[] filesWithSize = new String[files.length];
for(int i = 0; i<filesWithSize.length; ++i)
{
File filePath = new File(mWorkingDirectory+files[i]);
long mb = filePath.length()/(1024*1024);
filesWithSize[i] = files[i] + " ("+mb+" MB)";
}
ArrayList<HashMap<String, String> > arrayList = new ArrayList<HashMap<String, String> >();
for (int i = 0; i < filesWithSize.length; i++) {
HashMap<String, String> hashMap = new HashMap<String, String>();//create a hashmap to store the data in key value pair
hashMap.put("name", filesWithSize[i]);
hashMap.put("path", mWorkingDirectory + files[i]);
arrayList.add(hashMap);//add the hashmap into arrayList
}
String[] from = {"name", "path"};//string array
int[] to = {R.id.textView, R.id.imageView};//int array of views id's
DatabaseListArrayAdapter simpleAdapter = new DatabaseListArrayAdapter(this, arrayList, R.layout.database_list, from, to);//Create object and set the parameters for simpleAdapter
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Choose Your File (*.db)");
builder.setAdapter(simpleAdapter, new DialogInterface.OnClickListener() {
//builder.setItems(filesWithSize, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, final int which) {
// Adjust color now?
new AlertDialog.Builder(getActivity())
.setTitle("Opening database...")
.setMessage("Do you want to adjust colors now?\nThis can be done later under Optimize menu.")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichIn) {
openDatabase(files[which], true);
}
})
.setNeutralButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichIn) {
openDatabase(files[which], false);
}
})
.show();
return;
}
});
builder.show();
}
} }
else if(itemId == R.id.settings) else if(itemId == R.id.settings)
{ {
@@ -2008,6 +2050,170 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
return true; return true;
} }
private void openDatabase()
{
final String[] files = Util.loadFileList(mWorkingDirectory, true);
if(files.length > 0)
{
String[] filesWithSize = new String[files.length];
for(int i = 0; i<filesWithSize.length; ++i)
{
File filePath = new File(mWorkingDirectory+files[i]);
long mb = filePath.length()/(1024*1024);
filesWithSize[i] = files[i] + " ("+mb+" MB)";
}
ArrayList<HashMap<String, String> > arrayList = new ArrayList<HashMap<String, String> >();
for (int i = 0; i < filesWithSize.length; i++) {
HashMap<String, String> hashMap = new HashMap<String, String>();//create a hashmap to store the data in key value pair
hashMap.put("name", filesWithSize[i]);
hashMap.put("path", mWorkingDirectory + files[i]);
arrayList.add(hashMap);//add the hashmap into arrayList
}
String[] from = {"name", "path"};//string array
int[] to = {R.id.textView, R.id.imageView};//int array of views id's
DatabaseListArrayAdapter simpleAdapter = new DatabaseListArrayAdapter(this, arrayList, R.layout.database_list, from, to);//Create object and set the parameters for simpleAdapter
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Choose Your File (*.db)");
builder.setAdapter(simpleAdapter, new DialogInterface.OnClickListener() {
//builder.setItems(filesWithSize, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, final int which) {
// Adjust color now?
new AlertDialog.Builder(getActivity())
.setTitle("Opening database...")
.setMessage("Do you want to adjust colors now?\nThis can be done later under Optimize menu.")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichIn) {
openDatabase(files[which], true);
}
})
.setNeutralButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichIn) {
openDatabase(files[which], false);
}
})
.show();
return;
}
});
final AlertDialog ad = builder.create(); //don't show dialog yet
ad.setOnShowListener(new OnShowListener()
{
@Override
public void onShow(DialogInterface dialog)
{
ListView lv = ad.getListView();
ad.registerForContextMenu(lv);
lv.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
if (v.getId()==ad.getListView().getId()) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
final int position = info.position;
menu.setHeaderTitle(files[position]);
menu.add(Menu.NONE, 0, 0, "Rename").setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
AlertDialog.Builder builderRename = new AlertDialog.Builder(getActivity());
builderRename.setTitle("RTAB-Map Database Name (*.db):");
final EditText input = new EditText(getActivity());
input.setInputType(InputType.TYPE_CLASS_TEXT);
input.setText("");
input.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
input.setSelectAllOnFocus(true);
input.selectAll();
builderRename.setView(input);
builderRename.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which)
{
final String fileName = input.getText().toString();
dialog.dismiss();
if(!fileName.isEmpty())
{
File newFile = new File(mWorkingDirectory + fileName + ".db");
if(newFile.exists())
{
new AlertDialog.Builder(getActivity())
.setTitle("File Already Exists")
.setMessage(String.format("Name %s already used, choose another name.", fileName))
.show();
}
else
{
File from = new File(mWorkingDirectory, files[position]);
File to = new File(mWorkingDirectory, fileName + ".db");
from.renameTo(to);
ad.dismiss();
resetNoTouchTimer(true);
}
}
}
});
AlertDialog alertToShow = builderRename.create();
alertToShow.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
alertToShow.show();
return true;
}
});
menu.add(Menu.NONE, 1, 1, "Delete").setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which){
case DialogInterface.BUTTON_POSITIVE:
Log.e(TAG, String.format("Yes delete %s!", files[position]));
(new File(mWorkingDirectory+files[position])).delete();
ad.dismiss();
resetNoTouchTimer(true);
break;
case DialogInterface.BUTTON_NEGATIVE:
//No button clicked
break;
}
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(String.format("Delete %s", files[position]))
.setMessage("Are you sure?")
.setPositiveButton("Yes", dialogClickListener)
.setNegativeButton("No", dialogClickListener).show();
return true;
}
});
menu.add(Menu.NONE, 2, 2, "Share").setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
// Send to...
File f = new File(mWorkingDirectory+files[position]);
final int fileSizeMB = (int)f.length()/(1024 * 1024);
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f));
shareIntent.setType("application/octet-stream");
startActivity(Intent.createChooser(shareIntent, String.format("Sharing database \"%s\" (%d MB)...", files[position], fileSizeMB)));
ad.dismiss();
resetNoTouchTimer(true);
return true;
}
});
}
}
});
}
});
ad.show();
}
}
private void export(final boolean isOBJ, final boolean meshing, final boolean regenerateCloud, final boolean optimized, final int optimizedMaxPolygons) private void export(final boolean isOBJ, final boolean meshing, final boolean regenerateCloud, final boolean optimized, final int optimizedMaxPolygons)
{ {
final String extension = isOBJ? ".obj" : ".ply"; final String extension = isOBJ? ".obj" : ".ply";
@@ -2211,8 +2417,6 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
msg = String.format("Database saved to \"%s\".", newDatabasePathHuman); msg = String.format("Database saved to \"%s\".", newDatabasePathHuman);
} }
mToast.makeText(getActivity(), msg, mToast.LENGTH_LONG).show();
// build notification // build notification
Intent intent = new Intent(getActivity(), RTABMapActivity.class); Intent intent = new Intent(getActivity(), RTABMapActivity.class);
// use System.currentTimeMillis() to have a unique ID for the pending intent // use System.currentTimeMillis() to have a unique ID for the pending intent
@@ -2232,6 +2436,15 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
notificationManager.notify(0, n); notificationManager.notify(0, n);
// Send to...
File f = new File(newDatabasePath);
final int fileSizeMB = (int)f.length()/(1024 * 1024);
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f));
shareIntent.setType("application/octet-stream");
startActivity(Intent.createChooser(shareIntent, String.format("Database \"%s\" (%d MB) successfully saved on the SD-CARD! Share it?", newDatabasePathHuman, fileSizeMB)));
resetNoTouchTimer(true); resetNoTouchTimer(true);
if(!mItemDataRecorderMode.isChecked()) if(!mItemDataRecorderMode.isChecked())
{ {
@@ -2385,11 +2598,13 @@ public class RTABMapActivity extends Activity implements OnClickListener, OnItem
mProgressDialog.dismiss(); mProgressDialog.dismiss();
// Send to... // Send to...
File f = new File(zipOutput);
final int fileSizeMB = (int)f.length()/(1024 * 1024);
Intent shareIntent = new Intent(); Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND); shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(zipOutput))); shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f));
shareIntent.setType("application/zip"); shareIntent.setType("application/zip");
startActivity(Intent.createChooser(shareIntent, String.format("Mesh \"%s\" successfully exported! Share it?", pathHuman))); startActivity(Intent.createChooser(shareIntent, String.format("Mesh \"%s\" (%d MB) successfully exported on the SD-CARD! Share it?", pathHuman, fileSizeMB)));
resetNoTouchTimer(true); resetNoTouchTimer(true);
} }
@@ -92,6 +92,13 @@ public class RTABMapLib
public static native void setRenderingTextureDecimation(int value); public static native void setRenderingTextureDecimation(int value);
public static native void setBackgroundColor(float gray); public static native void setBackgroundColor(float gray);
public static native int setMappingParameter(String key, String value); public static native int setMappingParameter(String key, String value);
public static native void setGPS(
double stamp,
double longitude,
double latitude,
double altitude,
double accuracy,
double bearing);
public static native void resetMapping(); public static native void resetMapping();
public static native void save(String outputDatabasePath); public static native void save(String outputDatabasePath);
+2 -2
View File
@@ -159,7 +159,7 @@ public:
void getNodeData(int signatureId, SensorData & data, bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true) const; void getNodeData(int signatureId, SensorData & data, bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true) const;
bool getCalibration(int signatureId, std::vector<CameraModel> & models, StereoCameraModel & stereoModel) const; bool getCalibration(int signatureId, std::vector<CameraModel> & models, StereoCameraModel & stereoModel) const;
bool getLaserScanInfo(int signatureId, LaserScanInfo & info) const; bool getLaserScanInfo(int signatureId, LaserScanInfo & info) const;
bool getNodeInfo(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose, std::vector<float> & velocity) const; bool getNodeInfo(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose, std::vector<float> & velocity, std::vector<double> & gps) const;
void loadLinks(int signatureId, std::map<int, Link> & links, Link::Type type = Link::kUndef) const; void loadLinks(int signatureId, std::map<int, Link> & links, Link::Type type = Link::kUndef) const;
void getWeight(int signatureId, int & weight) const; void getWeight(int signatureId, int & weight) const;
void getAllNodeIds(std::set<int> & ids, bool ignoreChildren = false, bool ignoreBadSignatures = false) const; void getAllNodeIds(std::set<int> & ids, bool ignoreChildren = false, bool ignoreBadSignatures = false) const;
@@ -253,7 +253,7 @@ private:
virtual void loadNodeDataQuery(std::list<Signature *> & signatures, bool images=true, bool scan=true, bool userData=true, bool occupancyGrid=true) const = 0; virtual void loadNodeDataQuery(std::list<Signature *> & signatures, bool images=true, bool scan=true, bool userData=true, bool occupancyGrid=true) const = 0;
virtual bool getCalibrationQuery(int signatureId, std::vector<CameraModel> & models, StereoCameraModel & stereoModel) const = 0; virtual bool getCalibrationQuery(int signatureId, std::vector<CameraModel> & models, StereoCameraModel & stereoModel) const = 0;
virtual bool getLaserScanInfoQuery(int signatureId, LaserScanInfo & info) const = 0; virtual bool getLaserScanInfoQuery(int signatureId, LaserScanInfo & info) const = 0;
virtual bool getNodeInfoQuery(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose, std::vector<float> & velocity) const = 0; virtual bool getNodeInfoQuery(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose, std::vector<float> & velocity, std::vector<double> & gps) const = 0;
virtual void getAllNodeIdsQuery(std::set<int> & ids, bool ignoreChildren, bool ignoreBadSignatures) const = 0; virtual void getAllNodeIdsQuery(std::set<int> & ids, bool ignoreChildren, bool ignoreBadSignatures) const = 0;
virtual void getAllLinksQuery(std::multimap<int, Link> & links, bool ignoreNullLinks) const = 0; virtual void getAllLinksQuery(std::multimap<int, Link> & links, bool ignoreNullLinks) const = 0;
virtual void getLastIdQuery(const std::string & tableName, int & id) const = 0; virtual void getLastIdQuery(const std::string & tableName, int & id) const = 0;
+1
View File
@@ -177,6 +177,7 @@ public:
double & stamp, double & stamp,
Transform & groundTruth, Transform & groundTruth,
std::vector<float> & velocity, std::vector<float> & velocity,
std::vector<double> & gps,
bool lookInDatabase = false) const; bool lookInDatabase = false) const;
cv::Mat getImageCompressed(int signatureId) const; cv::Mat getImageCompressed(int signatureId) const;
SensorData getNodeData(int nodeId, bool uncompressedData = false) const; SensorData getNodeData(int nodeId, bool uncompressedData = false) const;
+14
View File
@@ -225,6 +225,18 @@ public:
const Transform & globalPose() const {return globalPose_;} const Transform & globalPose() const {return globalPose_;}
const cv::Mat & globalPoseCovariance() const {return globalPoseCovariance_;} const cv::Mat & globalPoseCovariance() const {return globalPoseCovariance_;}
void setGPS(double stamp, double longitude, double latitude, double altitude, double accuracy, double bearing)
{
gps_ = std::vector<double>(6,0.0);
gps_[0]=stamp;
gps_[1]=longitude;
gps_[2]=latitude;
gps_[3]=altitude;
gps_[4]=accuracy;
gps_[5]=bearing;
}
const std::vector<double> & gps() const {return gps_;}
long getMemoryUsed() const; // Return memory usage in Bytes long getMemoryUsed() const; // Return memory usage in Bytes
private: private:
@@ -265,6 +277,8 @@ private:
Transform globalPose_; Transform globalPose_;
cv::Mat globalPoseCovariance_; // 6x6 double cv::Mat globalPoseCovariance_; // 6x6 double
std::vector<double> gps_;
}; };
} }
+4 -2
View File
@@ -712,7 +712,8 @@ bool DBDriver::getNodeInfo(
std::string & label, std::string & label,
double & stamp, double & stamp,
Transform & groundTruthPose, Transform & groundTruthPose,
std::vector<float> & velocity) const std::vector<float> & velocity,
std::vector<double> & gps) const
{ {
bool found = false; bool found = false;
// look in the trash // look in the trash
@@ -725,6 +726,7 @@ bool DBDriver::getNodeInfo(
label = _trashSignatures.at(signatureId)->getLabel(); label = _trashSignatures.at(signatureId)->getLabel();
stamp = _trashSignatures.at(signatureId)->getStamp(); stamp = _trashSignatures.at(signatureId)->getStamp();
groundTruthPose = _trashSignatures.at(signatureId)->getGroundTruthPose(); groundTruthPose = _trashSignatures.at(signatureId)->getGroundTruthPose();
gps = _trashSignatures.at(signatureId)->sensorData().gps();
found = true; found = true;
} }
_trashesMutex.unlock(); _trashesMutex.unlock();
@@ -732,7 +734,7 @@ bool DBDriver::getNodeInfo(
if(!found) if(!found)
{ {
_dbSafeAccessMutex.lock(); _dbSafeAccessMutex.lock();
found = this->getNodeInfoQuery(signatureId, pose, mapId, weight, label, stamp, groundTruthPose, velocity); found = this->getNodeInfoQuery(signatureId, pose, mapId, weight, label, stamp, groundTruthPose, velocity, gps);
_dbSafeAccessMutex.unlock(); _dbSafeAccessMutex.unlock();
} }
return found; return found;
+68 -5
View File
@@ -497,7 +497,11 @@ long DBDriverSqlite3::getNodesMemoryUsedQuery() const
if(_ppDb) if(_ppDb)
{ {
std::string query; std::string query;
if(uStrNumCmp(_version, "0.13.0") >= 0) if(uStrNumCmp(_version, "0.14.0") >= 0)
{
query = "SELECT sum(length(id) + length(map_id) + length(weight) + length(pose) + length(stamp) + ifnull(length(label),0) + length(ground_truth_pose) + ifnull(length(velocity),0) + ifnull(length(gps),0) + length(time_enter)) from Node;";
}
else if(uStrNumCmp(_version, "0.13.0") >= 0)
{ {
query = "SELECT sum(length(id) + length(map_id) + length(weight) + length(pose) + length(stamp) + ifnull(length(label),0) + length(ground_truth_pose) + ifnull(length(velocity),0) + length(time_enter)) from Node;"; query = "SELECT sum(length(id) + length(map_id) + length(weight) + length(pose) + length(stamp) + ifnull(length(label),0) + length(ground_truth_pose) + ifnull(length(velocity),0) + length(time_enter)) from Node;";
} }
@@ -1751,7 +1755,8 @@ bool DBDriverSqlite3::getNodeInfoQuery(int signatureId,
std::string & label, std::string & label,
double & stamp, double & stamp,
Transform & groundTruthPose, Transform & groundTruthPose,
std::vector<float> & velocity) const std::vector<float> & velocity,
std::vector<double> & gps) const
{ {
bool found = false; bool found = false;
if(_ppDb && signatureId) if(_ppDb && signatureId)
@@ -1760,7 +1765,14 @@ bool DBDriverSqlite3::getNodeInfoQuery(int signatureId,
sqlite3_stmt * ppStmt = 0; sqlite3_stmt * ppStmt = 0;
std::stringstream query; std::stringstream query;
if(uStrNumCmp(_version, "0.13.0") >= 0) if(uStrNumCmp(_version, "0.14.0") >= 0)
{
query << "SELECT pose, map_id, weight, label, stamp, ground_truth_pose, velocity, gps "
"FROM Node "
"WHERE id = " << signatureId <<
";";
}
else if(uStrNumCmp(_version, "0.13.0") >= 0)
{ {
query << "SELECT pose, map_id, weight, label, stamp, ground_truth_pose, velocity " query << "SELECT pose, map_id, weight, label, stamp, ground_truth_pose, velocity "
"FROM Node " "FROM Node "
@@ -1839,6 +1851,17 @@ bool DBDriverSqlite3::getNodeInfoQuery(int signatureId,
memcpy(velocity.data(), data, dataSize); memcpy(velocity.data(), data, dataSize);
} }
} }
if(uStrNumCmp(_version, "0.14.0") >= 0)
{
gps.resize(6,0);
data = sqlite3_column_blob(ppStmt, index); // velocity
dataSize = sqlite3_column_bytes(ppStmt, index++);
if((unsigned int)dataSize == gps.size()*sizeof(double) && data)
{
memcpy(gps.data(), data, dataSize);
}
}
} }
} }
@@ -2239,7 +2262,13 @@ void DBDriverSqlite3::loadSignaturesQuery(const std::list<int> & ids, std::list<
unsigned int loaded = 0; unsigned int loaded = 0;
// Load nodes information // Load nodes information
if(uStrNumCmp(_version, "0.13.0") >= 0) if(uStrNumCmp(_version, "0.14.0") >= 0)
{
query << "SELECT id, map_id, weight, pose, stamp, label, ground_truth_pose, velocity, gps "
<< "FROM Node "
<< "WHERE id=?;";
}
else if(uStrNumCmp(_version, "0.13.0") >= 0)
{ {
query << "SELECT id, map_id, weight, pose, stamp, label, ground_truth_pose, velocity " query << "SELECT id, map_id, weight, pose, stamp, label, ground_truth_pose, velocity "
<< "FROM Node " << "FROM Node "
@@ -2281,6 +2310,7 @@ void DBDriverSqlite3::loadSignaturesQuery(const std::list<int> & ids, std::list<
Transform pose; Transform pose;
Transform groundTruthPose; Transform groundTruthPose;
std::vector<float> velocity; std::vector<float> velocity;
std::vector<double> gps;
const void * data = 0; const void * data = 0;
int dataSize = 0; int dataSize = 0;
std::string label; std::string label;
@@ -2329,6 +2359,17 @@ void DBDriverSqlite3::loadSignaturesQuery(const std::list<int> & ids, std::list<
memcpy(velocity.data(), data, dataSize); memcpy(velocity.data(), data, dataSize);
} }
} }
if(uStrNumCmp(_version, "0.14.0") >= 0)
{
gps.resize(6,0);
data = sqlite3_column_blob(ppStmt, index); // gps
dataSize = sqlite3_column_bytes(ppStmt, index++);
if((unsigned int)dataSize == gps.size()*sizeof(double) && data)
{
memcpy(gps.data(), data, dataSize);
}
}
} }
} }
@@ -2352,6 +2393,10 @@ void DBDriverSqlite3::loadSignaturesQuery(const std::list<int> & ids, std::list<
{ {
s->setVelocity(velocity[0], velocity[1], velocity[2], velocity[3], velocity[4], velocity[5]); s->setVelocity(velocity[0], velocity[1], velocity[2], velocity[3], velocity[4], velocity[5]);
} }
if(gps.size() == 6)
{
s->sensorData().setGPS(gps[0], gps[1], gps[2], gps[3], gps[4], gps[5]);
}
s->setSaved(true); s->setSaved(true);
nodes.push_back(s); nodes.push_back(s);
++loaded; ++loaded;
@@ -4213,7 +4258,11 @@ cv::Mat DBDriverSqlite3::loadOptimizedMeshQuery(
std::string DBDriverSqlite3::queryStepNode() const std::string DBDriverSqlite3::queryStepNode() const
{ {
if(uStrNumCmp(_version, "0.13.0") >= 0) if(uStrNumCmp(_version, "0.14.0") >= 0)
{
return "INSERT INTO Node(id, map_id, weight, pose, stamp, label, ground_truth_pose, velocity, gps) VALUES(?,?,?,?,?,?,?,?,?);";
}
else if(uStrNumCmp(_version, "0.13.0") >= 0)
{ {
return "INSERT INTO Node(id, map_id, weight, pose, stamp, label, ground_truth_pose, velocity) VALUES(?,?,?,?,?,?,?,?);"; return "INSERT INTO Node(id, map_id, weight, pose, stamp, label, ground_truth_pose, velocity) VALUES(?,?,?,?,?,?,?,?);";
} }
@@ -4293,6 +4342,20 @@ void DBDriverSqlite3::stepNode(sqlite3_stmt * ppStmt, const Signature * s) const
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str()); UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
} }
} }
if(uStrNumCmp(_version, "0.14.0") >= 0)
{
if(s->sensorData().gps().empty())
{
rc = sqlite3_bind_null(ppStmt, index++);
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
}
else
{
rc = sqlite3_bind_blob(ppStmt, index++, s->sensorData().gps().data(), s->sensorData().gps().size()*sizeof(double), SQLITE_STATIC);
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error (%s): %s", _version.c_str(), sqlite3_errmsg(_ppDb)).c_str());
}
}
} }
} }
else if(uStrNumCmp(_version, "0.8.8") >= 0) else if(uStrNumCmp(_version, "0.8.8") >= 0)
+1 -1
View File
@@ -127,7 +127,7 @@ private:
virtual void loadNodeDataQuery(std::list<Signature *> & signatures, bool images=true, bool scan=true, bool userData=true, bool occupancyGrid=true) const; virtual void loadNodeDataQuery(std::list<Signature *> & signatures, bool images=true, bool scan=true, bool userData=true, bool occupancyGrid=true) const;
virtual bool getCalibrationQuery(int signatureId, std::vector<CameraModel> & models, StereoCameraModel & stereoModel) const; virtual bool getCalibrationQuery(int signatureId, std::vector<CameraModel> & models, StereoCameraModel & stereoModel) const;
virtual bool getLaserScanInfoQuery(int signatureId, LaserScanInfo & info) const; virtual bool getLaserScanInfoQuery(int signatureId, LaserScanInfo & info) const;
virtual bool getNodeInfoQuery(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose, std::vector<float> & velocity) const; virtual bool getNodeInfoQuery(int signatureId, Transform & pose, int & mapId, int & weight, std::string & label, double & stamp, Transform & groundTruthPose, std::vector<float> & velocity, std::vector<double> & gps) const;
virtual void getAllNodeIdsQuery(std::set<int> & ids, bool ignoreChildren, bool ignoreBadSignatures) const; virtual void getAllNodeIdsQuery(std::set<int> & ids, bool ignoreChildren, bool ignoreBadSignatures) const;
virtual void getAllLinksQuery(std::multimap<int, Link> & links, bool ignoreNullLinks) const; virtual void getAllLinksQuery(std::multimap<int, Link> & links, bool ignoreNullLinks) const;
virtual void getLastIdQuery(const std::string & tableName, int & id) const; virtual void getLastIdQuery(const std::string & tableName, int & id) const;
+4 -2
View File
@@ -268,7 +268,8 @@ SensorData DBReader::captureImage(CameraInfo * info)
int mapId; int mapId;
Transform localTransform, pose, groundTruth; Transform localTransform, pose, groundTruth;
std::vector<float> velocity; std::vector<float> velocity;
_dbDriver->getNodeInfo(*_currentId, pose, mapId, weight, label, stamp, groundTruth, velocity); std::vector<double> gps;
_dbDriver->getNodeInfo(*_currentId, pose, mapId, weight, label, stamp, groundTruth, velocity, gps);
if(previousStamp && stamp && stamp > previousStamp) if(previousStamp && stamp && stamp > previousStamp)
{ {
delay = stamp - previousStamp; delay = stamp - previousStamp;
@@ -322,7 +323,8 @@ SensorData DBReader::getNextData(CameraInfo * info)
double stamp; double stamp;
Transform groundTruth; Transform groundTruth;
std::vector<float> velocity; std::vector<float> velocity;
_dbDriver->getNodeInfo(*_currentId, pose, mapId, weight, label, stamp, groundTruth, velocity); std::vector<double> gps;
_dbDriver->getNodeInfo(*_currentId, pose, mapId, weight, label, stamp, groundTruth, velocity, gps);
cv::Mat infMatrix = cv::Mat::eye(6,6,CV_64FC1); cv::Mat infMatrix = cv::Mat::eye(6,6,CV_64FC1);
if(!_odometryIgnored) if(!_odometryIgnored)
+11 -3
View File
@@ -3051,7 +3051,8 @@ Transform Memory::getOdomPose(int signatureId, bool lookInDatabase) const
std::string label; std::string label;
double stamp; double stamp;
std::vector<float> velocity; std::vector<float> velocity;
getNodeInfo(signatureId, pose, mapId, weight, label, stamp, groundTruth, velocity, lookInDatabase); std::vector<double> gps;
getNodeInfo(signatureId, pose, mapId, weight, label, stamp, groundTruth, velocity, gps, lookInDatabase);
return pose; return pose;
} }
@@ -3062,7 +3063,8 @@ Transform Memory::getGroundTruthPose(int signatureId, bool lookInDatabase) const
std::string label; std::string label;
double stamp; double stamp;
std::vector<float> velocity; std::vector<float> velocity;
getNodeInfo(signatureId, pose, mapId, weight, label, stamp, groundTruth, velocity, lookInDatabase); std::vector<double> gps;
getNodeInfo(signatureId, pose, mapId, weight, label, stamp, groundTruth, velocity, gps, lookInDatabase);
return groundTruth; return groundTruth;
} }
@@ -3074,6 +3076,7 @@ bool Memory::getNodeInfo(int signatureId,
double & stamp, double & stamp,
Transform & groundTruth, Transform & groundTruth,
std::vector<float> & velocity, std::vector<float> & velocity,
std::vector<double> & gps,
bool lookInDatabase) const bool lookInDatabase) const
{ {
const Signature * s = this->getSignature(signatureId); const Signature * s = this->getSignature(signatureId);
@@ -3086,11 +3089,12 @@ bool Memory::getNodeInfo(int signatureId,
stamp = s->getStamp(); stamp = s->getStamp();
groundTruth = s->getGroundTruthPose(); groundTruth = s->getGroundTruthPose();
velocity = s->getVelocity(); velocity = s->getVelocity();
gps = s->sensorData().gps();
return true; return true;
} }
else if(lookInDatabase && _dbDriver) else if(lookInDatabase && _dbDriver)
{ {
return _dbDriver->getNodeInfo(signatureId, odomPose, mapId, weight, label, stamp, groundTruth, velocity); return _dbDriver->getNodeInfo(signatureId, odomPose, mapId, weight, label, stamp, groundTruth, velocity, gps);
} }
return false; return false;
} }
@@ -3963,6 +3967,10 @@ Signature * Memory::createSignature(const SensorData & data, const Transform & p
s->sensorData().setUserDataRaw(data.userDataRaw()); s->sensorData().setUserDataRaw(data.userDataRaw());
s->sensorData().setGroundTruth(data.groundTruth()); s->sensorData().setGroundTruth(data.groundTruth());
if(!data.gps().empty())
{
s->sensorData().setGPS(data.gps()[0], data.gps()[1], data.gps()[2], data.gps()[3], data.gps()[4], data.gps()[5]);
}
t = timer.ticks(); t = timer.ticks();
if(stats) stats->addStatistic(Statistics::kTimingMemCompressing_data(), t*1000.0f); if(stats) stats->addStatistic(Statistics::kTimingMemCompressing_data(), t*1000.0f);
+20 -4
View File
@@ -761,7 +761,8 @@ void Rtabmap::exportPoses(const std::string & path, bool optimized, bool global,
std::string l; std::string l;
double stamp = 0.0; double stamp = 0.0;
std::vector<float> v; std::vector<float> v;
_memory->getNodeInfo(iter->first, o, m, w, l, stamp, g, v, true); std::vector<double> gps;
_memory->getNodeInfo(iter->first, o, m, w, l, stamp, g, v, gps, true);
stamps.insert(std::make_pair(iter->first, stamp)); stamps.insert(std::make_pair(iter->first, stamp));
} }
} }
@@ -2650,7 +2651,8 @@ bool Rtabmap::process(
double stamp = 0; double stamp = 0;
Transform groundTruth; Transform groundTruth;
std::vector<float> velocity; std::vector<float> velocity;
_memory->getNodeInfo(iter->first, odomPoseLocal, mapId, weight, label, stamp, groundTruth, velocity, false); std::vector<double> gps;
_memory->getNodeInfo(iter->first, odomPoseLocal, mapId, weight, label, stamp, groundTruth, velocity, gps, false);
signatures.insert(std::make_pair(iter->first, signatures.insert(std::make_pair(iter->first,
Signature(iter->first, Signature(iter->first,
mapId, mapId,
@@ -2663,6 +2665,10 @@ bool Rtabmap::process(
{ {
signatures.at(iter->first).setVelocity(velocity[0], velocity[1], velocity[2], velocity[3], velocity[4], velocity[5]); signatures.at(iter->first).setVelocity(velocity[0], velocity[1], velocity[2], velocity[3], velocity[4], velocity[5]);
} }
if(!gps.empty())
{
signatures.at(iter->first).sensorData().setGPS(gps[0], gps[1], gps[2], gps[3], gps[4], gps[5]);
}
} }
localGraphSize = (int)poses.size(); localGraphSize = (int)poses.size();
if(!lastSignatureLocalizedPose.isNull()) if(!lastSignatureLocalizedPose.isNull())
@@ -3340,7 +3346,8 @@ void Rtabmap::get3DMap(
double stamp = 0; double stamp = 0;
Transform groundTruth; Transform groundTruth;
std::vector<float> velocity; std::vector<float> velocity;
_memory->getNodeInfo(*iter, odomPoseLocal, mapId, weight, label, stamp, groundTruth, velocity, true); std::vector<double> gps;
_memory->getNodeInfo(*iter, odomPoseLocal, mapId, weight, label, stamp, groundTruth, velocity, gps, true);
SensorData data = _memory->getNodeData(*iter); SensorData data = _memory->getNodeData(*iter);
data.setId(*iter); data.setId(*iter);
std::multimap<int, cv::KeyPoint> words; std::multimap<int, cv::KeyPoint> words;
@@ -3363,6 +3370,10 @@ void Rtabmap::get3DMap(
{ {
signatures.at(*iter).setVelocity(velocity[0], velocity[1], velocity[2], velocity[3], velocity[4], velocity[5]); signatures.at(*iter).setVelocity(velocity[0], velocity[1], velocity[2], velocity[3], velocity[4], velocity[5]);
} }
if(!gps.empty())
{
signatures.at(*iter).sensorData().setGPS(gps[0], gps[1], gps[2], gps[3], gps[4], gps[5]);
}
} }
} }
else if(_memory && (_memory->getStMem().size() || _memory->getWorkingMem().size() > 1)) else if(_memory && (_memory->getStMem().size() || _memory->getWorkingMem().size() > 1))
@@ -3415,7 +3426,8 @@ void Rtabmap::getGraph(
double stamp = 0; double stamp = 0;
Transform groundTruth; Transform groundTruth;
std::vector<float> velocity; std::vector<float> velocity;
_memory->getNodeInfo(iter->first, odomPoseLocal, mapId, weight, label, stamp, groundTruth, velocity, global); std::vector<double> gps;
_memory->getNodeInfo(iter->first, odomPoseLocal, mapId, weight, label, stamp, groundTruth, velocity, gps, global);
signatures->insert(std::make_pair(iter->first, signatures->insert(std::make_pair(iter->first,
Signature(iter->first, Signature(iter->first,
mapId, mapId,
@@ -3443,6 +3455,10 @@ void Rtabmap::getGraph(
{ {
signatures->at(iter->first).setVelocity(velocity[0], velocity[1], velocity[2], velocity[3], velocity[4], velocity[5]); signatures->at(iter->first).setVelocity(velocity[0], velocity[1], velocity[2], velocity[3], velocity[4], velocity[5]);
} }
if(!gps.empty())
{
signatures->at(iter->first).sensorData().setGPS(gps[0], gps[1], gps[2], gps[3], gps[4], gps[5]);
}
} }
} }
} }
@@ -22,6 +22,7 @@ CREATE TABLE Node (
ground_truth_pose BLOB, -- 3x4 float ground_truth_pose BLOB, -- 3x4 float
velocity BLOB, -- 6 float (vx,vy,vz,vroll,vpitch,vyaw) m/s and rad/s velocity BLOB, -- 6 float (vx,vy,vz,vroll,vpitch,vyaw) m/s and rad/s
label TEXT, label TEXT,
gps BLOB, -- 1x6 double: stamp, longitude (DD), latitude (DD), altitude (m), accuracy (m), bearing (North 0->360 deg clockwise)
time_enter DATE, time_enter DATE,
PRIMARY KEY (id) PRIMARY KEY (id)
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<package> <package>
<name>rtabmap</name> <name>rtabmap</name>
<version>0.13.3</version> <version>0.14.0</version>
<description>RTAB-Map's standalone library. RTAB-Map is a RGB-D SLAM approach with real-time constraints.</description> <description>RTAB-Map's standalone library. RTAB-Map is a RGB-D SLAM approach with real-time constraints.</description>
<maintainer email="[email protected]">Mathieu Labbe</maintainer> <maintainer email="[email protected]">Mathieu Labbe</maintainer>
<author>Mathieu Labbe</author> <author>Mathieu Labbe</author>