diff --git a/AreaLearningJava/app/src/main/java/com/projecttango/experiments/javaarealearning/AreaLearningActivity.java b/AreaLearningJava/app/src/main/java/com/projecttango/experiments/javaarealearning/AreaLearningActivity.java
index 4c804325..ae1e5e99 100644
--- a/AreaLearningJava/app/src/main/java/com/projecttango/experiments/javaarealearning/AreaLearningActivity.java
+++ b/AreaLearningJava/app/src/main/java/com/projecttango/experiments/javaarealearning/AreaLearningActivity.java
@@ -18,12 +18,10 @@
import com.google.atap.tangoservice.Tango.OnTangoUpdateListener;
import com.google.atap.tangoservice.Tango;
-import com.google.atap.tangoservice.TangoAreaDescriptionMetaData;
import com.google.atap.tangoservice.TangoConfig;
import com.google.atap.tangoservice.TangoCoordinateFramePair;
import com.google.atap.tangoservice.TangoErrorException;
import com.google.atap.tangoservice.TangoEvent;
-import com.google.atap.tangoservice.TangoException;
import com.google.atap.tangoservice.TangoInvalidException;
import com.google.atap.tangoservice.TangoOutOfDateException;
import com.google.atap.tangoservice.TangoPoseData;
@@ -34,7 +32,6 @@
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
@@ -43,14 +40,14 @@
import android.widget.TextView;
import android.widget.Toast;
-import java.text.DecimalFormat;
-import java.util.ArrayList;
-
import com.projecttango.tangoutils.TangoPoseUtilities;
import org.rajawali3d.surface.IRajawaliSurface;
import org.rajawali3d.surface.RajawaliSurfaceView;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+
/**
* Main Activity class for the Area Learning API Sample. Handles the connection to the Tango service
* and propagation of Tango pose data to OpenGL and Layout views. OpenGL rendering logic is
@@ -60,7 +57,7 @@ public class AreaLearningActivity extends Activity implements View.OnClickListen
SetADFNameDialog.CallbackListener, SaveAdfTask.SaveAdfListener {
private static final String TAG = AreaLearningActivity.class.getSimpleName();
- private static final int SECONDS_TO_MILLI = 1000;
+ private static final int SECS_TO_MILLISECS = 1000;
private Tango mTango;
private TangoConfig mConfig;
private TextView mTangoEventTextView;
@@ -102,6 +99,9 @@ public class AreaLearningActivity extends Activity implements View.OnClickListen
private double mAdf2DevicePreviousPoseTimeStamp;
private double mAdf2StartPreviousPoseTimeStamp;
+ private double mPreviousPoseTimeStamp;
+ private double mTimeToNextUpdate = UPDATE_INTERVAL_MS;
+
private boolean mIsRelocalized;
private boolean mIsLearningMode;
private boolean mIsConstantSpaceRelocalize;
@@ -113,9 +113,10 @@ public class AreaLearningActivity extends Activity implements View.OnClickListen
private SaveAdfTask mSaveAdfTask;
private TangoPoseData[] mPoses;
- private static final int UPDATE_INTERVAL_MS = 100;
- private static final DecimalFormat mThreeDecimalFormat = new DecimalFormat("00.000");
- private static final Object mSharedLock = new Object();
+ private static final double UPDATE_INTERVAL_MS = 100.0;
+ private static final DecimalFormat FORMAT_THREE_DECIMAL = new DecimalFormat("00.000");
+
+ private final Object mSharedLock = new Object();
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -140,8 +141,6 @@ protected void onCreate(Bundle savedInstanceState) {
mStart2DevicePoseCount = 0;
mAdf2DevicePoseCount = 0;
mAdf2StartPoseCount = 0;
-
- startUIThread();
}
/**
@@ -405,7 +404,6 @@ public void onPoseAvailable(TangoPoseData pose) {
// UI loop doesn't interfere while Pose call back is updating
// the data.
synchronized (mSharedLock) {
- float[] translation = pose.getTranslationAsFloats();
// Check for Device wrt ADF pose, Device wrt Start of Service pose,
// Start of Service wrt ADF pose(This pose determines if device
// the is relocalized or not).
@@ -421,7 +419,7 @@ public void onPoseAvailable(TangoPoseData pose) {
// Calculate time difference between current and last available Device wrt
// ADF pose.
mAdf2DevicePoseDelta = (pose.timestamp - mAdf2DevicePreviousPoseTimeStamp)
- * SECONDS_TO_MILLI;
+ * SECS_TO_MILLISECS;
mAdf2DevicePreviousPoseTimeStamp = pose.timestamp;
if (mIsRelocalized) {
updateRenderer = true;
@@ -438,7 +436,7 @@ public void onPoseAvailable(TangoPoseData pose) {
// Calculate time difference between current and last available Device wrt
// SS pose.
mStart2DevicePoseDelta = (pose.timestamp - mStart2DevicePreviousPoseTimeStamp)
- * SECONDS_TO_MILLI;
+ * SECS_TO_MILLISECS;
mStart2DevicePreviousPoseTimeStamp = pose.timestamp;
if (!mIsRelocalized) {
updateRenderer = true;
@@ -456,7 +454,7 @@ public void onPoseAvailable(TangoPoseData pose) {
// Calculate time difference between current and last available SS wrt ADF
// pose.
mAdf2StartPoseDelta = (pose.timestamp - mAdf2StartPreviousPoseTimeStamp)
- * SECONDS_TO_MILLI;
+ * SECS_TO_MILLISECS;
mAdf2StartPreviousPoseTimeStamp = pose.timestamp;
if (pose.statusCode == TangoPoseData.POSE_VALID) {
mIsRelocalized = true;
@@ -467,6 +465,24 @@ public void onPoseAvailable(TangoPoseData pose) {
}
}
}
+
+ final double deltaTime = (pose.timestamp - mPreviousPoseTimeStamp) * SECS_TO_MILLISECS;
+ mPreviousPoseTimeStamp = pose.timestamp;
+ mTimeToNextUpdate -= deltaTime;
+
+ if (mTimeToNextUpdate < 0.0) {
+ mTimeToNextUpdate = UPDATE_INTERVAL_MS;
+
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mSharedLock) {
+ updateTextViews();
+ }
+ }
+ });
+ }
+
if (updateRenderer) {
mRenderer.updateDevicePose(pose, mIsRelocalized);
}
@@ -527,42 +543,6 @@ private void showSetADFNameDialog() {
setADFNameDialog.show(manager, "ADFNameDialog");
}
- /**
- * Create a separate thread to update Log information on UI at the specified interval of
- * UPDATE_INTERVAL_MS. This function also makes sure to have access to the mPoses atomically.
- */
- private void startUIThread() {
- new Thread(new Runnable() {
- @Override
- public void run() {
- while (true) {
- try {
- Thread.sleep(UPDATE_INTERVAL_MS);
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- try {
- synchronized (mSharedLock) {
-
- if (mPoses == null) {
- return;
- } else {
- updateTextViews();
- }
- }
- } catch (NullPointerException e) {
- e.printStackTrace();
- }
- }
- });
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }).start();
- }
-
/**
* Updates the text view in UI screen with the Pose. Each pose is associated with Target and
* Base Frame. We need to check for that pair and update our views accordingly.
@@ -571,34 +551,31 @@ private void updateTextViews() {
// Allow clicking of the save button only when Tango is localized to the current ADF.
mSaveAdfButton.setEnabled(mIsRelocalized);
- if (mPoses[0] != null
- && mPoses[0].baseFrame == TangoPoseData.COORDINATE_FRAME_AREA_DESCRIPTION
+ if (mPoses[0] != null && mPoses[0].baseFrame == TangoPoseData.COORDINATE_FRAME_AREA_DESCRIPTION
&& mPoses[0].targetFrame == TangoPoseData.COORDINATE_FRAME_DEVICE) {
- mAdf2DeviceTranslationTextView.setText(TangoPoseUtilities.getTranslationString(mPoses[0], mThreeDecimalFormat));
- mAdf2DeviceQuatTextView.setText(TangoPoseUtilities.getQuaternionString(mPoses[0], mThreeDecimalFormat));
+ mAdf2DeviceTranslationTextView.setText(TangoPoseUtilities.getTranslationString(mPoses[0], FORMAT_THREE_DECIMAL));
+ mAdf2DeviceQuatTextView.setText(TangoPoseUtilities.getQuaternionString(mPoses[0], FORMAT_THREE_DECIMAL));
mAdf2DevicePoseStatusTextView.setText(TangoPoseUtilities.getStatusString(mPoses[0]));
mAdf2DevicePoseCountTextView.setText(Integer.toString(mAdf2DevicePoseCount));
- mAdf2DevicePoseDeltaTextView.setText(mThreeDecimalFormat.format(mAdf2DevicePoseDelta));
+ mAdf2DevicePoseDeltaTextView.setText(FORMAT_THREE_DECIMAL.format(mAdf2DevicePoseDelta));
}
- if (mPoses[1] != null
- && mPoses[1].baseFrame == TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE
+ if (mPoses[1] != null && mPoses[1].baseFrame == TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE
&& mPoses[1].targetFrame == TangoPoseData.COORDINATE_FRAME_DEVICE) {
- mStart2DeviceTranslationTextView.setText(TangoPoseUtilities.getTranslationString(mPoses[1], mThreeDecimalFormat));
- mStart2DeviceQuatTextView.setText(TangoPoseUtilities.getQuaternionString(mPoses[1], mThreeDecimalFormat));
+ mStart2DeviceTranslationTextView.setText(TangoPoseUtilities.getTranslationString(mPoses[1], FORMAT_THREE_DECIMAL));
+ mStart2DeviceQuatTextView.setText(TangoPoseUtilities.getQuaternionString(mPoses[1], FORMAT_THREE_DECIMAL));
mStart2DevicePoseStatusTextView.setText(TangoPoseUtilities.getStatusString(mPoses[1]));
mStart2DevicePoseCountTextView.setText(Integer.toString(mStart2DevicePoseCount));
- mStart2DevicePoseDeltaTextView.setText(mThreeDecimalFormat.format(mStart2DevicePoseDelta));
+ mStart2DevicePoseDeltaTextView.setText(FORMAT_THREE_DECIMAL.format(mStart2DevicePoseDelta));
}
- if (mPoses[2] != null
- && mPoses[2].baseFrame == TangoPoseData.COORDINATE_FRAME_AREA_DESCRIPTION
+ if (mPoses[2] != null && mPoses[2].baseFrame == TangoPoseData.COORDINATE_FRAME_AREA_DESCRIPTION
&& mPoses[2].targetFrame == TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE) {
- mAdf2StartTranslationTextView.setText(TangoPoseUtilities.getTranslationString(mPoses[2], mThreeDecimalFormat));
- mAdf2StartQuatTextView.setText(TangoPoseUtilities.getQuaternionString(mPoses[2], mThreeDecimalFormat));
+ mAdf2StartTranslationTextView.setText(TangoPoseUtilities.getTranslationString(mPoses[2], FORMAT_THREE_DECIMAL));
+ mAdf2StartQuatTextView.setText(TangoPoseUtilities.getQuaternionString(mPoses[2], FORMAT_THREE_DECIMAL));
mAdf2StartPoseStatusTextView.setText(TangoPoseUtilities.getStatusString(mPoses[2]));
mAdf2StartPoseCountTextView.setText(Integer.toString(mAdf2StartPoseCount));
- mAdf2StartPoseDeltaTextView.setText(mThreeDecimalFormat.format(mAdf2StartPoseDelta));
+ mAdf2StartPoseDeltaTextView.setText(FORMAT_THREE_DECIMAL.format(mAdf2StartPoseDelta));
}
}
}
diff --git a/AreaLearningJava/gradle/wrapper/gradle-wrapper.jar b/AreaLearningJava/gradle/wrapper/gradle-wrapper.jar
index 8c0fb64a..c97a8bdb 100644
Binary files a/AreaLearningJava/gradle/wrapper/gradle-wrapper.jar and b/AreaLearningJava/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/AugmentedRealitySample/app/src/main/java/com/projecttango/experiments/augmentedrealitysample/AugmentedRealityActivity.java b/AugmentedRealitySample/app/src/main/java/com/projecttango/experiments/augmentedrealitysample/AugmentedRealityActivity.java
index d2f00123..4fb55ad5 100644
--- a/AugmentedRealitySample/app/src/main/java/com/projecttango/experiments/augmentedrealitysample/AugmentedRealityActivity.java
+++ b/AugmentedRealitySample/app/src/main/java/com/projecttango/experiments/augmentedrealitysample/AugmentedRealityActivity.java
@@ -13,10 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.projecttango.experiments.augmentedrealitysample;
import android.app.Activity;
-import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
@@ -33,39 +33,45 @@
import com.google.atap.tangoservice.TangoOutOfDateException;
import com.google.atap.tangoservice.TangoPoseData;
import com.google.atap.tangoservice.TangoXyzIjData;
-import com.projecttango.rajawali.ar.TangoRajawaliView;
-import com.projecttango.tangosupport.TangoSupport;
import java.util.ArrayList;
+import com.projecttango.rajawali.ar.TangoRajawaliView;
+import com.projecttango.tangosupport.TangoPointCloudManager;
+import com.projecttango.tangosupport.TangoSupport;
+import com.projecttango.tangosupport.TangoSupport.IntersectionPointPlaneModelPair;
+
/**
- * An example showing how to build a very simple augmented reality application in Java.
- * It uses Rajawali to do the rendering through the utility classes
- * TangoRajawaliRenderer
and TangoRajawaliView
from TangoUtils.
- * It also uses the TangoSupportLibrary to do plane fitting using the PointCloud data. Whenever the
- * user clicks on the camera display, plane detection will be done on the surface closest to the
- * click location and a 3D object will be placed in the scene anchored in that location.
+ * An example showing how to build a very simple augmented reality application
+ * in Java. It uses Rajawali to do the rendering through the utility classes
+ * TangoRajawaliRenderer
and TangoRajawaliView
from
+ * TangoUtils. It also uses the TangoSupportLibrary to do plane fitting using
+ * the PointCloud data. Whenever the user clicks on the camera display, plane
+ * detection will be done on the surface closest to the click location and a 3D
+ * object will be placed in the scene anchored in that location.
*
- * TangoRajawaliView is used in the same way as the TangoCameraPreview: We first need initialize the
- * TangoRajawaliView class with the activity's context and connect to the camera we want by using
- * connectToTangoCamera method. Once the connection is established we need to update
- * the view's texture by using the onFrameAvailable callbacks.
+ * TangoRajawaliView is used in the same way as the TangoCameraPreview: We first
+ * need initialize the TangoRajawaliView class with the activity's context and
+ * connect to the camera we want by using connectToTangoCamera method. Once the
+ * connection is established we need to update the view's texture by using the
+ * onFrameAvailable callbacks.
*
- * The TangoRajawaliRenderer class is used the same way as a RajawaliRenderer. We need to create it
- * with a reference to the activity's context and then pass it to the view with the view's
- * setSurfaceRenderer method.
- * The implementation of the 3D world is done by subclassing the Renderer, just like any other
+ * The TangoRajawaliRenderer class is used the same way as a RajawaliRenderer.
+ * We need to create it with a reference to the activity's context and then pass
+ * it to the view with the view's setSurfaceRenderer method. The implementation
+ * of the 3D world is done by subclassing the Renderer, just like any other
* Rajawali application.
*
- * Note that it is important to include the KEY_BOOLEAN_LOWLATENCYIMUINTEGRATION configuration
- * parameter in order to achieve best results synchronizing the Rajawali virtual world with
- * the RGB camera.
+ * Note that it is important to include the KEY_BOOLEAN_LOWLATENCYIMUINTEGRATION
+ * configuration parameter in order to achieve best results synchronizing the
+ * Rajawali virtual world with the RGB camera.
*/
public class AugmentedRealityActivity extends Activity implements View.OnTouchListener {
private static final String TAG = AugmentedRealityActivity.class.getSimpleName();
private TangoRajawaliView mGLView;
private AugmentedRealityRenderer mRenderer;
- private PointCloudManager mPointCloudManager;
+ private TangoCameraIntrinsics mCameraIntrinsics;
+ private TangoPointCloudManager mPointCloudManager;
private Tango mTango;
private boolean mIsConnected;
@@ -80,25 +86,31 @@ protected void onCreate(Bundle savedInstanceState) {
setContentView(mGLView);
}
- // Augmented reality view and renderer
- private void startAugmentedreality() {
+ // Augmented reality view and renderer.
+ private void startAugmentedReality() {
if (!mIsConnected) {
try {
mIsConnected = true;
// Connect to color camera.
- mGLView.connectToTangoCamera(mTango, TangoCameraIntrinsics.TANGO_CAMERA_COLOR);
+ mGLView.connectToTangoCamera(mTango,
+ TangoCameraIntrinsics.TANGO_CAMERA_COLOR);
- // Use default configuration for Tango Service, plus low latency IMU integration.
- TangoConfig config = mTango.getConfig(TangoConfig.CONFIG_TYPE_DEFAULT);
- // NOTE: Low latency integration is necessary to achieve a precise alignment of
- // virtual objects with the RBG image and produce a good AR effect.
- config.putBoolean(TangoConfig.KEY_BOOLEAN_LOWLATENCYIMUINTEGRATION, true);
+ // Use default configuration for Tango Service, plus low latency
+ // IMU integration.
+ TangoConfig config = mTango.getConfig(
+ TangoConfig.CONFIG_TYPE_DEFAULT);
+ // NOTE: Low latency integration is necessary to achieve a
+ // precise alignment of virtual objects with the RBG image and
+ // produce a good AR effect.
+ config.putBoolean(
+ TangoConfig.KEY_BOOLEAN_LOWLATENCYIMUINTEGRATION, true);
config.putBoolean(TangoConfig.KEY_BOOLEAN_DEPTH, true);
mTango.connect(config);
- // No need to add any coordinate frame pairs since we are not using
- // pose data. So just initialize.
- ArrayList framePairs = new ArrayList();
+ // No need to add any coordinate frame pairs since we are not
+ // using pose data. So just initialize.
+ ArrayList framePairs =
+ new ArrayList();
mTango.connectListener(framePairs, new OnTangoUpdateListener() {
@Override
public void onPoseAvailable(TangoPoseData pose) {
@@ -107,8 +119,8 @@ public void onPoseAvailable(TangoPoseData pose) {
@Override
public void onFrameAvailable(int cameraId) {
- // Check if the frame available is for the camera we want and
- // update its frame on the view.
+ // Check if the frame available is for the camera we
+ // want and update its frame on the view.
if (cameraId == TangoCameraIntrinsics.TANGO_CAMERA_COLOR) {
mGLView.onFrameAvailable();
}
@@ -117,7 +129,7 @@ public void onFrameAvailable(int cameraId) {
@Override
public void onXyzIjAvailable(TangoXyzIjData xyzIj) {
// Save the cloud and point data for later use.
- mPointCloudManager.updateXyzIjData(xyzIj);
+ mPointCloudManager.updateXyzIj(xyzIj);
}
@Override
@@ -126,23 +138,24 @@ public void onTangoEvent(TangoEvent event) {
}
});
- // Get extrinsics from device for use in transforms. This needs to be done after
- // connecting Tango and listeners.
+ // Get extrinsics from device for use in transforms. This needs
+ // to be done after connecting Tango and listeners.
setupExtrinsics();
- // Setup point cloud plane fitting library helper class.
- mPointCloudManager = new PointCloudManager(mTango.getCameraIntrinsics(
- TangoCameraIntrinsics.TANGO_CAMERA_COLOR));
+ mCameraIntrinsics = mTango.getCameraIntrinsics(
+ TangoCameraIntrinsics.TANGO_CAMERA_COLOR);
+ mPointCloudManager = new TangoPointCloudManager();
} catch (TangoOutOfDateException e) {
- Toast.makeText(getApplicationContext(), R.string.TangoOutOfDateException,
- Toast.LENGTH_SHORT).show();
+ Toast.makeText(getApplicationContext(),
+ R.string.TangoOutOfDateException,
+ Toast.LENGTH_SHORT).show();
}
}
}
/**
- * Calculates and stores the fixed transformations between the device and the various sensors
- * to be used later for transformations between frames.
+ * Calculates and stores the fixed transformations between the device and
+ * the various sensors to be used later for transformations between frames.
*/
private void setupExtrinsics() {
// Create camera to IMU transform.
@@ -177,7 +190,7 @@ protected void onPause() {
protected void onResume() {
super.onResume();
if (!mIsConnected) {
- startAugmentedreality();
+ startAugmentedReality();
}
}
@@ -191,12 +204,14 @@ public boolean onTouch(View view, MotionEvent motionEvent) {
try {
doFitPlane(u, v);
} catch (TangoException t) {
- Toast.makeText(getApplicationContext(), R.string.failed_measurement,
- Toast.LENGTH_SHORT).show();
+ Toast.makeText(getApplicationContext(),
+ R.string.failed_measurement,
+ Toast.LENGTH_SHORT).show();
Log.e(TAG, getString(R.string.failed_measurement), t);
} catch (SecurityException t) {
- Toast.makeText(getApplicationContext(), R.string.failed_permissions,
- Toast.LENGTH_SHORT).show();
+ Toast.makeText(getApplicationContext(),
+ R.string.failed_permissions,
+ Toast.LENGTH_SHORT).show();
Log.e(TAG, getString(R.string.failed_permissions), t);
}
}
@@ -204,29 +219,40 @@ public boolean onTouch(View view, MotionEvent motionEvent) {
}
/**
- * Use the TangoSupport library with point cloud data to calculate the plane of
- * the world feature pointed at the location the camera is looking at and update the
- * renderer to show a 3D object in that location.
+ * Use the TangoSupport library with point cloud data to calculate the plane
+ * of the world feature pointed at the location the camera is looking at and
+ * update the renderer to show a 3D object in that location.
*/
private void doFitPlane(float u, float v) {
- // NOTE: We request measurement at the latest available time. If we wanted to be even more
- // precise, we should use the timestamp of the RGB image rendered at the time the user
- // clicked the screen
+ // NOTE: We request measurement at the latest available time. If we
+ // wanted to be even more precise, we should use the timestamp of the
+ // RGB image rendered at the time the user clicked the screen.
double measurementTimestamp = 0.0;
+ TangoXyzIjData xyzIj = mPointCloudManager.getLatestXyzIj();
+
+ // We need to calculate the transform between the color camera at the
+ // time the user clicked and the depth camera at the time the depth
+ // cloud was acquired.
+ TangoPoseData colorTdepthPose = TangoSupport.calculateRelativePose(
+ measurementTimestamp,
+ TangoPoseData.COORDINATE_FRAME_CAMERA_COLOR, xyzIj.timestamp,
+ TangoPoseData.COORDINATE_FRAME_CAMERA_DEPTH);
// Perform plane fitting with the latest available point cloud data.
- PointCloudManager.FitPlaneResult planeModelAndTimestamp =
- mPointCloudManager.fitPlane(u, v, measurementTimestamp);
+ IntersectionPointPlaneModelPair intersectionPointPlaneModelPair =
+ TangoSupport.fitPlaneModelNearClick(xyzIj, mCameraIntrinsics,
+ colorTdepthPose, u, v);
// Get the device pose at the time the plane data was acquired.
TangoCoordinateFramePair framePair = new TangoCoordinateFramePair(
TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE,
TangoPoseData.COORDINATE_FRAME_DEVICE);
TangoPoseData devicePose =
- mTango.getPoseAtTime(planeModelAndTimestamp.cloudTimestamp, framePair);
+ mTango.getPoseAtTime(xyzIj.timestamp, framePair);
- // Update the AR object location
- mRenderer.updateObjectPose(planeModelAndTimestamp.planeModelPair.intersectionPoint,
- planeModelAndTimestamp.planeModelPair.planeModel, devicePose);
+ // Update the AR object location.
+ mRenderer.updateObjectPose(
+ intersectionPointPlaneModelPair.intersectionPoint,
+ intersectionPointPlaneModelPair.planeModel, devicePose);
}
}
diff --git a/AugmentedRealitySample/app/src/main/java/com/projecttango/experiments/augmentedrealitysample/AugmentedRealityRenderer.java b/AugmentedRealitySample/app/src/main/java/com/projecttango/experiments/augmentedrealitysample/AugmentedRealityRenderer.java
index 1679b94a..79d6677b 100644
--- a/AugmentedRealitySample/app/src/main/java/com/projecttango/experiments/augmentedrealitysample/AugmentedRealityRenderer.java
+++ b/AugmentedRealitySample/app/src/main/java/com/projecttango/experiments/augmentedrealitysample/AugmentedRealityRenderer.java
@@ -19,8 +19,6 @@
import android.view.MotionEvent;
import com.google.atap.tangoservice.TangoPoseData;
-import com.projecttango.rajawali.Pose;
-import com.projecttango.rajawali.ar.TangoRajawaliRenderer;
import org.rajawali3d.Object3D;
import org.rajawali3d.lights.DirectionalLight;
@@ -31,15 +29,20 @@
import org.rajawali3d.math.vector.Vector3;
import org.rajawali3d.primitives.Cube;
+import com.projecttango.rajawali.Pose;
+import com.projecttango.rajawali.ar.TangoRajawaliRenderer;
+
/**
- * Very simple example augmented reality renderer which displays two objects in a fixed position
- * in the world and the uses the Tango position tracking to keep them in place.
+ * Very simple example augmented reality renderer which displays two objects in
+ * a fixed position in the world and the uses the Tango position tracking to
+ * keep them in place.
*
- * This follows the same development model than any regular Rajawali application with the following
- * peculiarities:
- * - It extends TangoRajawaliArRenderer
- * - It calls super.initScene()
in the initialization
- * - It doesn't do anything with the camera, since that is handled automatically by Tango
+ * This follows the same development model than any regular Rajawali application
+ * with the following peculiarities:
+ * - It extends TangoRajawaliArRenderer
.
+ * - It calls super.initScene()
in the initialization.
+ * - It doesn't do anything with the camera, since that is handled automatically
+ * by Tango.
*/
public class AugmentedRealityRenderer extends TangoRajawaliRenderer {
private static final float CUBE_SIDE_LENGTH = 0.5f;
@@ -55,7 +58,8 @@ public AugmentedRealityRenderer(Context context) {
@Override
protected void initScene() {
- // Remember to call super.initScene() to allow TangoRajawaliArRenderer to be set-up.
+ // Remember to call super.initScene() to allow TangoRajawaliArRenderer
+ // to be set-up.
super.initScene();
// Add a directional light in an arbitrary direction.
@@ -65,7 +69,8 @@ protected void initScene() {
light.setPosition(3, 2, 4);
getCurrentScene().addLight(light);
- // Set-up a material: green with application of the light and instructions.
+ // Set-up a material: green with application of the light and
+ // instructions.
Material material = new Material();
material.setColor(0xff009900);
try {
@@ -96,25 +101,29 @@ protected void onRender(long elapsedRealTime, double deltaTime) {
// Place the 3D object in the location of the detected plane.
mObject.setPosition(mPlanePose.getPosition());
mObject.setOrientation(mPlanePose.getOrientation());
- // Move it forward by half of the size of the cube to make it flush with the plane
- // surface.
+ // Move it forward by half of the size of the cube to make it
+ // flush with the plane surface.
mObject.moveForward(CUBE_SIDE_LENGTH / 2.0f);
}
}
}
/**
- * Update the 3D object based on the provided measurement point, normal (in depth frame) and
- * device pose at the time the point and normal were acquired.
+ * Update the 3D object based on the provided measurement point, normal (in
+ * depth frame) and device pose at the time the point and normal were
+ * acquired.
*/
public synchronized void updateObjectPose(double[] point, double[] normal,
TangoPoseData devicePose) {
- mPlanePose = mScenePoseCalcuator.planeFitToOpenGLPose(point, normal, devicePose);
+ mPlanePose = mScenePoseCalcuator.planeFitToOpenGLPose(point, normal,
+ devicePose);
mPlanePoseUpdated = true;
}
@Override
- public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) {
+ public void onOffsetsChanged(float xOffset, float yOffset,
+ float xOffsetStep, float yOffsetStep,
+ int xPixelOffset, int yPixelOffset) {
}
diff --git a/AugmentedRealitySample/app/src/main/res/menu/main.xml b/AugmentedRealitySample/app/src/main/res/menu/main.xml
deleted file mode 100644
index 76c1d564..00000000
--- a/AugmentedRealitySample/app/src/main/res/menu/main.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
diff --git a/AugmentedRealitySample/app/src/main/res/values/strings.xml b/AugmentedRealitySample/app/src/main/res/values/strings.xml
index 1679b024..8cf24e22 100644
--- a/AugmentedRealitySample/app/src/main/res/values/strings.xml
+++ b/AugmentedRealitySample/app/src/main/res/values/strings.xml
@@ -2,8 +2,8 @@
AugmentedRealitySample
- Settings
"Tango service outdated!"
Failed to fit plane
Permissions required!
+
diff --git a/AugmentedRealitySample/gradle/wrapper/gradle-wrapper.jar b/AugmentedRealitySample/gradle/wrapper/gradle-wrapper.jar
index 8c0fb64a..c97a8bdb 100644
Binary files a/AugmentedRealitySample/gradle/wrapper/gradle-wrapper.jar and b/AugmentedRealitySample/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/MotionTrackingJava/app/src/main/java/com/projecttango/experiments/javamotiontracking/MotionTrackingActivity.java b/MotionTrackingJava/app/src/main/java/com/projecttango/experiments/javamotiontracking/MotionTrackingActivity.java
index 589c1d79..e29035a5 100644
--- a/MotionTrackingJava/app/src/main/java/com/projecttango/experiments/javamotiontracking/MotionTrackingActivity.java
+++ b/MotionTrackingJava/app/src/main/java/com/projecttango/experiments/javamotiontracking/MotionTrackingActivity.java
@@ -25,7 +25,6 @@
import com.google.atap.tangoservice.TangoOutOfDateException;
import com.google.atap.tangoservice.TangoPoseData;
import com.google.atap.tangoservice.TangoXyzIjData;
-import com.projecttango.tangoutils.TangoPoseUtilities;
import android.app.Activity;
import android.content.Intent;
@@ -39,6 +38,8 @@
import android.widget.TextView;
import android.widget.Toast;
+import com.projecttango.tangoutils.TangoPoseUtilities;
+
import org.rajawali3d.surface.IRajawaliSurface;
import org.rajawali3d.surface.RajawaliSurfaceView;
@@ -54,7 +55,9 @@ public class MotionTrackingActivity extends Activity implements View.OnClickList
private static final String TAG = MotionTrackingActivity.class.getSimpleName();
private static final int SECS_TO_MILLISECS = 1000;
- private static final int UPDATE_INTERVAL_MS = 100;
+ private static final double UPDATE_INTERVAL_MS = 100.0f;
+ private static final DecimalFormat FORMAT_THREE_DECIMAL = new DecimalFormat("0.000");
+
private Tango mTango;
private TangoConfig mConfig;
private TextView mDeltaTextView;
@@ -66,14 +69,16 @@ public class MotionTrackingActivity extends Activity implements View.OnClickList
private TextView mApplicationVersionTextView;
private TextView mTangoEventTextView;
private Button mMotionResetButton;
- private float mPreviousTimeStamp;
- private int mPreviousPoseStatus;
- private int mCount;
- private float mDeltaTime;
private boolean mIsAutoRecovery;
private MotionTrackingRajawaliRenderer mRenderer;
- private TangoPoseData mPose;
- public static Object mUiThreadLock = new Object();
+
+ // State tracking variables for pose callback handler. If these are
+ // referenced from the main thread, they need to be synchronized with the
+ // pose handler callback.
+ private double mPreviousTimeStamp = 0.0;
+ private int mPreviousPoseStatus = TangoPoseData.POSE_INVALID;
+ private int mCount = 0;
+ private double mTimeToNextUpdate = UPDATE_INTERVAL_MS;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -87,9 +92,8 @@ protected void onCreate(Bundle savedInstanceState) {
mConfig = setupTangoConfig(mTango, mIsAutoRecovery);
setupTextViewsAndButtons(mConfig);
mRenderer = setupGLViewAndRenderer();
- startUIThread();
}
-
+
/**
* Sets Rajawalisurface view and its renderer. This is ideally called only once in onCreate.
*/
@@ -179,32 +183,63 @@ private void setTangoListeners() {
// Listen for new Tango data
mTango.connectListener(framePairs, new OnTangoUpdateListener() {
-
@Override
public void onPoseAvailable(final TangoPoseData pose) {
- // Update the OpenGL renderable objects with the new Tango Pose data.
- // Note that locking for thread safe access with the OpenGL loop is done entirely
- // in the renderer.
+ // Update the OpenGL renderable objects with the new Tango Pose
+ // data. Note that locking for thread safe access with the
+ // OpenGL loop is done entirely in the renderer.
mRenderer.updateDevicePose(pose);
-
- // Make sure to have atomic access to Tango Pose Data so that the UI
- // the UI loop doesn't interfere while Pose call back is updating the data
- synchronized (mUiThreadLock) {
- mPose = pose;
-
- //Now lets log some interesting statistics of Motion Tracking like
- // Delta Time between two Poses, number of poses since the initialization state.
- mDeltaTime = (float) (pose.timestamp - mPreviousTimeStamp) * SECS_TO_MILLISECS;
- mPreviousTimeStamp = (float) pose.timestamp;
- // Log whenever Motion Tracking enters an invalid state
- if (!mIsAutoRecovery && (pose.statusCode == TangoPoseData.POSE_INVALID)) {
- Log.w(TAG, "Invalid State");
- }
- if (mPreviousPoseStatus != pose.statusCode) {
- mCount = 0;
- }
- mCount++;
- mPreviousPoseStatus = pose.statusCode;
+
+ // Now lets log some interesting statistics of Motion Tracking
+ // like Delta Time between two Poses, number of poses since the
+ // initialization state.
+ final double deltaTime = (pose.timestamp - mPreviousTimeStamp)
+ * SECS_TO_MILLISECS;
+
+ mPreviousTimeStamp = pose.timestamp;
+ // Log whenever Motion Tracking enters an invalid state
+ if (!mIsAutoRecovery && (pose.statusCode == TangoPoseData.POSE_INVALID)) {
+ Log.w(TAG, "Invalid State");
+ }
+ if (mPreviousPoseStatus != pose.statusCode) {
+ mCount = 0;
+ }
+ mCount++;
+ final int count = mCount;
+ mPreviousPoseStatus = pose.statusCode;
+
+ // Throttle updates to the UI based on UPDATE_INTERVAL_MS.
+ mTimeToNextUpdate -= deltaTime;
+ boolean updateUI = false;
+ if(mTimeToNextUpdate < 0.0) {
+ mTimeToNextUpdate = UPDATE_INTERVAL_MS;
+ updateUI = true;
+ }
+
+ // If the pose is not valid, we may not get another callback so make sure to update
+ // the UI during this call
+ if (pose.statusCode != TangoPoseData.POSE_VALID) {
+ updateUI = true;
+ }
+
+ if(updateUI) {
+ final String translationString =
+ TangoPoseUtilities.getTranslationString(pose, FORMAT_THREE_DECIMAL);
+ final String quaternionString =
+ TangoPoseUtilities.getQuaternionString(pose, FORMAT_THREE_DECIMAL);
+ final String status = TangoPoseUtilities.getStatusString(pose);
+
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // Display pose data on screen in TextViews.
+ mPoseTextView.setText(translationString);
+ mQuatTextView.setText(quaternionString);
+ mPoseCountTextView.setText(Integer.toString(count));
+ mDeltaTextView.setText(FORMAT_THREE_DECIMAL.format(deltaTime));
+ mPoseStatusTextView.setText(status);
+ }
+ });
}
}
@@ -301,51 +336,4 @@ public boolean onTouchEvent(MotionEvent event) {
mRenderer.onTouchEvent(event);
return true;
}
-
- /**
- * Create a separate thread to update Log information on UI at the specified
- * interval of UPDATE_INTERVAL_MS. This function also makes sure to have access
- * to the mPose atomically.
- */
- private void startUIThread() {
- new Thread(new Runnable() {
- DecimalFormat threeDec = new DecimalFormat("00.000");
- @Override
- public void run() {
- while (true) {
- try {
- Thread.sleep(UPDATE_INTERVAL_MS);
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- try {
- synchronized (mUiThreadLock) {
- if (mPose == null) {
- return;
- }
- String translationString =
- TangoPoseUtilities.getTranslationString(mPose, threeDec);
- String quaternionString =
- TangoPoseUtilities.getQuaternionString(mPose, threeDec);
- String status = TangoPoseUtilities.getStatusString(mPose);
- // Display pose data on screen in TextViews
- mPoseTextView.setText(translationString);
- mQuatTextView.setText(quaternionString);
- mPoseCountTextView.setText(Integer.toString(mCount));
- mDeltaTextView.setText(threeDec.format(mDeltaTime));
- mPoseStatusTextView.setText(status);
- }
- } catch (NullPointerException e) {
- e.printStackTrace();
- }
- }
- });
-
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }).start();
- }
-}
\ No newline at end of file
+}
diff --git a/MotionTrackingJava/gradle/wrapper/gradle-wrapper.jar b/MotionTrackingJava/gradle/wrapper/gradle-wrapper.jar
index 8c0fb64a..c97a8bdb 100644
Binary files a/MotionTrackingJava/gradle/wrapper/gradle-wrapper.jar and b/MotionTrackingJava/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/PointCloudJava/app/src/main/java/com/projecttango/experiments/javapointcloud/PointCloudActivity.java b/PointCloudJava/app/src/main/java/com/projecttango/experiments/javapointcloud/PointCloudActivity.java
index 18065b42..16aa85ee 100644
--- a/PointCloudJava/app/src/main/java/com/projecttango/experiments/javapointcloud/PointCloudActivity.java
+++ b/PointCloudJava/app/src/main/java/com/projecttango/experiments/javapointcloud/PointCloudActivity.java
@@ -15,6 +15,10 @@
*/
package com.projecttango.experiments.javapointcloud;
+
+import com.google.atap.tango.ux.TangoUx;
+import com.google.atap.tango.ux.TangoUx.StartParams;
+import com.google.atap.tango.ux.TangoUxLayout;
import com.google.atap.tango.ux.UxExceptionEvent;
import com.google.atap.tango.ux.UxExceptionEventListener;
import com.google.atap.tangoservice.Tango;
@@ -28,12 +32,6 @@
import com.google.atap.tangoservice.TangoPoseData;
import com.google.atap.tangoservice.TangoXyzIjData;
-import com.google.atap.tango.ux.TangoUx;
-import com.google.atap.tango.ux.TangoUx.StartParams;
-import com.google.atap.tango.ux.TangoUxLayout;
-import com.projecttango.tangoutils.TangoPoseUtilities;
-
-
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageInfo;
@@ -47,6 +45,8 @@
import android.widget.TextView;
import android.widget.Toast;
+import com.projecttango.tangoutils.TangoPoseUtilities;
+
import org.rajawali3d.surface.RajawaliSurfaceView;
import java.lang.Override;
@@ -85,22 +85,19 @@ public class PointCloudActivity extends Activity implements OnClickListener {
private Button mTopDownButton;
private int mCount;
- private int mPreviousPoseStatus;
- private int mPointCount;
- private float mDeltaTime;
- private float mPosePreviousTimeStamp;
- private float mXyIjPreviousTimeStamp;
- private float mCurrentTimeStamp;
- private float mPointCloudFrameDelta;
- private float mAverageDepth;
+ private int mPreviousPoseStatus = TangoPoseData.POSE_INVALID;
+ private double mPosePreviousTimeStamp;
+ private double mXyIjPreviousTimeStamp;
private boolean mIsTangoServiceConnected;
private TangoPoseData mPose;
private PointCloudManager mPointCloudManager;
private TangoUx mTangoUx;
- private static final int UPDATE_INTERVAL_MS = 100;
- private Object mUiPoseLock = new Object();
- private Object mUiDepthLock = new Object();
+ private static final DecimalFormat FORMAT_THREE_DECIMAL = new DecimalFormat("0.000");
+ private static final double UPDATE_INTERVAL_MS = 100.0;
+
+ private double mPoseTimeToNextUpdate = UPDATE_INTERVAL_MS;
+ private double mXyzIjTimeToNextUpdate = UPDATE_INTERVAL_MS;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -117,7 +114,6 @@ protected void onCreate(Bundle savedInstanceState) {
mRenderer = setupGLViewAndRenderer(mPointCloudManager);
mTangoUx = setupTangoUxAndLayout();
mIsTangoServiceConnected = false;
- startUIThread();
}
@Override
@@ -203,21 +199,41 @@ public void onPoseAvailable(final TangoPoseData pose) {
if (mTangoUx != null) {
mTangoUx.updatePoseStatus(pose.statusCode);
}
- // Make sure to have atomic access to Tango Pose Data so that
- // render loop doesn't interfere while Pose call back is updating
- // the data.
- synchronized (mUiPoseLock) {
- mPose = pose;
- // Calculate the delta time from previous pose.
- mDeltaTime = (float) (pose.timestamp - mPosePreviousTimeStamp)
- * SECS_TO_MILLISECS;
- mPosePreviousTimeStamp = (float) pose.timestamp;
- if (mPreviousPoseStatus != pose.statusCode) {
- mCount = 0;
- }
- mCount++;
- mPreviousPoseStatus = pose.statusCode;
+
+ mPose = pose;
+ // Calculate the delta time from previous pose.
+ final double deltaTime = (pose.timestamp - mPosePreviousTimeStamp)
+ * SECS_TO_MILLISECS;
+ mPosePreviousTimeStamp = pose.timestamp;
+ if (mPreviousPoseStatus != pose.statusCode) {
+ mCount = 0;
+ }
+ mCount++;
+ mPreviousPoseStatus = pose.statusCode;
+ mPoseTimeToNextUpdate -= deltaTime;
+
+ if (mPoseTimeToNextUpdate < 0.0) {
+ mPoseTimeToNextUpdate = UPDATE_INTERVAL_MS;
+
+ final String translationString
+ = TangoPoseUtilities.getTranslationString(mPose, FORMAT_THREE_DECIMAL);
+ final String quaternionString
+ = TangoPoseUtilities.getQuaternionString(mPose, FORMAT_THREE_DECIMAL);
+ final String status = TangoPoseUtilities.getStatusString(mPose);
+ final String countString = Integer.toString(mCount);
+
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mPoseTextView.setText(translationString);
+ mQuatTextView.setText(quaternionString);
+ mPoseCountTextView.setText(countString);
+ mDeltaTextView.setText(FORMAT_THREE_DECIMAL.format(deltaTime));
+ mPoseStatusTextView.setText(status);
+ }
+ });
}
+
mRenderer.updateDevicePose(pose);
}
@@ -227,28 +243,30 @@ public void onXyzIjAvailable(final TangoXyzIjData xyzIj) {
mTangoUx.updateXyzCount(xyzIj.xyzCount);
}
mPointCloudManager.updateCallbackBufferAndSwap(xyzIj.xyz, xyzIj.xyzCount);
- TangoPoseData pointCloudPose = mTango.getPoseAtTime(mCurrentTimeStamp,
+ TangoPoseData pointCloudPose = mTango.getPoseAtTime(xyzIj.timestamp,
framePairs.get(0));
mRenderer.updatePointCloudPose(pointCloudPose);
- // Make sure to have atomic access to TangoXyzIjData so that
- // UI loop doesn't interfere while onXYZijAvailable callback is updating
- // the mPoint cloud data.
- synchronized (mUiDepthLock) {
- mCurrentTimeStamp = (float) xyzIj.timestamp;
- mPointCloudFrameDelta = (mCurrentTimeStamp - mXyIjPreviousTimeStamp)
- * SECS_TO_MILLISECS;
- mXyIjPreviousTimeStamp = mCurrentTimeStamp;
- mAverageDepth = getAveragedDepth(xyzIj.xyz);
- try {
- mPointCount = xyzIj.xyzCount;
- } catch (TangoErrorException e) {
- Toast.makeText(getApplicationContext(), R.string.TangoError,
- Toast.LENGTH_SHORT).show();
- } catch (TangoInvalidException e) {
- Toast.makeText(getApplicationContext(), R.string.TangoError,
- Toast.LENGTH_SHORT).show();
- }
+ final double currentTimeStamp = xyzIj.timestamp;
+ final double pointCloudFrameDelta = (currentTimeStamp - mXyIjPreviousTimeStamp)
+ * SECS_TO_MILLISECS;
+ mXyIjPreviousTimeStamp = currentTimeStamp;
+ final double averageDepth = getAveragedDepth(xyzIj.xyz);
+
+ mXyzIjTimeToNextUpdate -= pointCloudFrameDelta;
+
+ if (mXyzIjTimeToNextUpdate < 0.0) {
+ mXyzIjTimeToNextUpdate = UPDATE_INTERVAL_MS;
+ final String pointCountString = Integer.toString(xyzIj.xyzCount);
+
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mPointCountTextView.setText(pointCountString);
+ mFrequencyTextView.setText(FORMAT_THREE_DECIMAL.format(pointCloudFrameDelta));
+ mAverageZTextView.setText(FORMAT_THREE_DECIMAL.format(averageDepth));
+ }
+ });
}
}
@@ -272,53 +290,6 @@ public void onFrameAvailable(int cameraId) {
});
}
- /**
- * Create a separate thread to update Log information on UI at the specified interval of
- * UPDATE_INTERVAL_MS. This function also makes sure to have access to the mPose atomically.
- */
- private void startUIThread() {
- new Thread(new Runnable() {
- final DecimalFormat threeDec = new DecimalFormat("0.000");
-
- @Override
- public void run() {
- while (true) {
- try {
- Thread.sleep(UPDATE_INTERVAL_MS);
- // Update the UI with TangoPose information
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- synchronized (mUiPoseLock) {
- if (mPose == null) {
- return;
- }
- String translationString = TangoPoseUtilities.getTranslationString(mPose, threeDec);
- String quaternionString = TangoPoseUtilities.getQuaternionString(mPose, threeDec);
- String status = TangoPoseUtilities.getStatusString(mPose);
- mPoseTextView.setText(translationString);
- mQuatTextView.setText(quaternionString);
- mPoseCountTextView.setText(Integer.toString(mCount));
- mDeltaTextView.setText(threeDec.format(mDeltaTime));
- mPoseStatusTextView.setText(status);
- }
- synchronized (mUiDepthLock) {
- // Display number of points in the mPoint cloud
- mPointCountTextView.setText(Integer.toString(mPointCount));
- mFrequencyTextView.setText(""
- + threeDec.format(mPointCloudFrameDelta));
- mAverageZTextView.setText("" + threeDec.format(mAverageDepth));
- }
- }
- });
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }).start();
- }
-
private void setupExtrinsics() {
TangoCoordinateFramePair framePair = new TangoCoordinateFramePair();
framePair.baseFrame = TangoPoseData.COORDINATE_FRAME_IMU;
@@ -453,14 +424,14 @@ private TangoUx setupTangoUxAndLayout(){
* @return Average depth.
*/
private float getAveragedDepth(FloatBuffer pointCloudBuffer){
- mPointCount = pointCloudBuffer.capacity() / 3;
+ int pointCount = pointCloudBuffer.capacity() / 3;
float totalZ = 0;
float averageZ = 0;
for (int i = 0; i < pointCloudBuffer.capacity() - 3; i = i + 3) {
totalZ = totalZ + pointCloudBuffer.get(i + 2);
}
- if (mPointCount != 0)
- averageZ = totalZ / mPointCount;
+ if (pointCount != 0)
+ averageZ = totalZ / pointCount;
return averageZ;
}
diff --git a/PointCloudJava/gradle/wrapper/gradle-wrapper.jar b/PointCloudJava/gradle/wrapper/gradle-wrapper.jar
index 8c0fb64a..c97a8bdb 100644
Binary files a/PointCloudJava/gradle/wrapper/gradle-wrapper.jar and b/PointCloudJava/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/QuickstartJava/app/src/main/java/com/projecttango/experiments/quickstartjava/MainActivity.java b/QuickstartJava/app/src/main/java/com/projecttango/experiments/quickstartjava/MainActivity.java
index f1fac3ab..dfd1aa95 100644
--- a/QuickstartJava/app/src/main/java/com/projecttango/experiments/quickstartjava/MainActivity.java
+++ b/QuickstartJava/app/src/main/java/com/projecttango/experiments/quickstartjava/MainActivity.java
@@ -16,8 +16,6 @@
package com.projecttango.experiments.quickstartjava;
-import java.util.ArrayList;
-
import com.google.atap.tangoservice.Tango;
import com.google.atap.tangoservice.Tango.OnTangoUpdateListener;
import com.google.atap.tangoservice.TangoConfig;
@@ -37,6 +35,7 @@
import android.widget.TextView;
import android.widget.Toast;
+import java.util.ArrayList;
/**
* Main Activity for the Tango Java Quickstart. Demonstrates establishing a
@@ -49,13 +48,19 @@ public class MainActivity extends Activity {
private static final String sTranslationFormat = "Translation: %f, %f, %f";
private static final String sRotationFormat = "Rotation: %f, %f, %f, %f";
+ private static final int SECS_TO_MILLISECS = 1000;
+ private static final double UPDATE_INTERVAL_MS = 100.0;
+
+ private double mPreviousTimeStamp;
+ private double mTimeToNextUpdate = UPDATE_INTERVAL_MS;
+
private TextView mTranslationTextView;
private TextView mRotationTextView;
private Tango mTango;
private TangoConfig mConfig;
private boolean mIsTangoServiceConnected;
- private boolean mIsProcessing = false;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -137,12 +142,6 @@ private void setTangoListeners() {
@SuppressLint("DefaultLocale")
@Override
public void onPoseAvailable(TangoPoseData pose) {
- if (mIsProcessing) {
- Log.i(TAG, "Processing UI");
- return;
- }
- mIsProcessing = true;
-
// Format Translation and Rotation data
final String translationMsg = String.format(sTranslationFormat,
pose.translation[0], pose.translation[1],
@@ -155,19 +154,28 @@ public void onPoseAvailable(TangoPoseData pose) {
String logMsg = translationMsg + " | " + rotationMsg;
Log.i(TAG, logMsg);
- // Display data in TextViews. This must be done inside a
- // runOnUiThread call because
- // it affects the UI, which will cause an error if performed
- // from the Tango
- // service thread
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mTranslationTextView.setText(translationMsg);
- mRotationTextView.setText(rotationMsg);
- mIsProcessing = false;
- }
- });
+ final double deltaTime = (pose.timestamp - mPreviousTimeStamp)
+ * SECS_TO_MILLISECS;
+ mPreviousTimeStamp = pose.timestamp;
+ mTimeToNextUpdate -= deltaTime;
+
+ // Throttle updates to the UI based on UPDATE_INTERVAL_MS.
+ if (mTimeToNextUpdate < 0.0) {
+ mTimeToNextUpdate = UPDATE_INTERVAL_MS;
+
+ // Display data in TextViews. This must be done inside a
+ // runOnUiThread call because
+ // it affects the UI, which will cause an error if performed
+ // from the Tango
+ // service thread
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mRotationTextView.setText(rotationMsg);
+ mTranslationTextView.setText(translationMsg);
+ }
+ });
+ }
}
@Override
diff --git a/QuickstartJava/gradle/wrapper/gradle-wrapper.jar b/QuickstartJava/gradle/wrapper/gradle-wrapper.jar
index 8c0fb64a..c97a8bdb 100644
Binary files a/QuickstartJava/gradle/wrapper/gradle-wrapper.jar and b/QuickstartJava/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/TangoReleaseLibs/aar/TangoUtils.aar b/TangoReleaseLibs/aar/TangoUtils.aar
index 189cbad2..8c379cdb 100644
Binary files a/TangoReleaseLibs/aar/TangoUtils.aar and b/TangoReleaseLibs/aar/TangoUtils.aar differ
diff --git a/TangoReleaseLibs/aar/tango-ux-support-library.aar b/TangoReleaseLibs/aar/tango-ux-support-library.aar
index dc181b25..1248aa50 100644
Binary files a/TangoReleaseLibs/aar/tango-ux-support-library.aar and b/TangoReleaseLibs/aar/tango-ux-support-library.aar differ
diff --git a/TangoReleaseLibs/aar/tango_support_java_lib.aar b/TangoReleaseLibs/aar/tango_support_java_lib.aar
index 4df01320..317b06a1 100644
Binary files a/TangoReleaseLibs/aar/tango_support_java_lib.aar and b/TangoReleaseLibs/aar/tango_support_java_lib.aar differ
diff --git a/TangoReleaseLibs/jar/tango_java_lib.jar b/TangoReleaseLibs/jar/tango_java_lib.jar
index 63199d65..8f81273f 100644
Binary files a/TangoReleaseLibs/jar/tango_java_lib.jar and b/TangoReleaseLibs/jar/tango_java_lib.jar differ
diff --git a/TangoUtils/gradle/wrapper/gradle-wrapper.jar b/TangoUtils/gradle/wrapper/gradle-wrapper.jar
index 8c0fb64a..c97a8bdb 100644
Binary files a/TangoUtils/gradle/wrapper/gradle-wrapper.jar and b/TangoUtils/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/VideoOverlaySample/app/src/main/AndroidManifest.xml b/VideoOverlaySample/app/src/main/AndroidManifest.xml
index 04c2e995..4e03a93d 100644
--- a/VideoOverlaySample/app/src/main/AndroidManifest.xml
+++ b/VideoOverlaySample/app/src/main/AndroidManifest.xml
@@ -7,7 +7,7 @@
-
+