Skip to content
This repository was archived by the owner on Mar 2, 2018. It is now read-only.

Commit a412348

Browse files
committed
release zeno
1 parent f89352e commit a412348

File tree

16 files changed

+482
-132
lines changed

16 files changed

+482
-132
lines changed

AreaLearningJava/app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ if (project.hasProperty("Tango.catkin_devel_prefix")) {
3636
}
3737

3838
dependencies {
39+
compile fileTree(dir: external_lib_prefix + '/jar', include: ['**/*.jar'])
3940
compile(name: 'TangoUtils', ext: 'aar')
4041
compile 'org.rajawali3d:rajawali:1.0.294-SNAPSHOT@aar'
4142
}

AugmentedRealitySample/app/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ if (project.hasProperty("Tango.catkin_devel_prefix")) {
3737
}
3838

3939
dependencies {
40-
compile(name: 'TangoUtils', ext: 'aar')
40+
compile (name: 'TangoUtils', ext: 'aar')
41+
compile (name: 'tango_support_java_lib', ext: 'aar')
4142
compile 'org.rajawali3d:rajawali:1.0.294-SNAPSHOT@aar'
4243
}
4344

AugmentedRealitySample/app/src/main/java/com/projecttango/experiments/augmentedrealitysample/AugmentedRealityActivity.java

Lines changed: 90 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@
1616
package com.projecttango.experiments.augmentedrealitysample;
1717

1818
import java.util.ArrayList;
19-
import java.util.concurrent.atomic.AtomicBoolean;
2019

2120
import android.app.Activity;
2221
import android.content.Intent;
2322
import android.os.Bundle;
23+
import android.util.Log;
24+
import android.view.MotionEvent;
25+
import android.view.View;
2426
import android.widget.Toast;
2527

2628
import com.google.atap.tangoservice.Tango;
@@ -32,11 +34,15 @@
3234
import com.google.atap.tangoservice.TangoPoseData;
3335
import com.google.atap.tangoservice.TangoXyzIjData;
3436
import com.projecttango.rajawali.ar.TangoRajawaliView;
37+
import com.projecttango.tangosupport.TangoSupport;
3538

3639
/**
3740
* An example showing how to build a very simple augmented reality application in Java.
3841
* It uses Rajawali to do the rendering through the utility classes
3942
* <code>TangoRajawaliRenderer</code> and <code>TangoRajawaliView</code> from TangoUtils.
43+
* It also uses the TangoSupportLibrary to do plane fitting using the PointCloud data. Whenever the
44+
* user clicks on the camera display, plane detection will be done on the surface closest to the
45+
* click location and a 3D object will be placed in the scene anchored in that location.
4046
* <p/>
4147
* TangoRajawaliView is used in the same way as the TangoCamaraPreview: we first need initialize the
4248
* TangoRajawaliView class with the activity's context and connect to the camera we want by using
@@ -49,12 +55,15 @@
4955
* The implementation of the 3D world is done by subclassing the Renderer, just like any other
5056
* Rajawali application.
5157
* <p/>
52-
* Note that it is important to include the KEY_BOOLEAN_LOWLATENCYIMUINTEGRATION configuration parameter in
53-
* order to achieve best results synchronizing the Rajawali virtual world with the RGB camera.
58+
* Note that it is important to include the KEY_BOOLEAN_LOWLATENCYIMUINTEGRATION configuration
59+
* parameter in order to achieve best results synchronizing the Rajawali virtual world with
60+
* the RGB camera.
5461
*/
55-
public class AugmentedRealityActivity extends Activity {
62+
public class AugmentedRealityActivity extends Activity implements View.OnTouchListener {
63+
private static final String TAG = "AugmentedRealityActiv";
5664
private TangoRajawaliView mGLView;
5765
private AugmentedRealityRenderer mRenderer;
66+
private PointCloudManager mPointCloudManager;
5867
private Tango mTango;
5968
private boolean mIsConnected;
6069
private boolean mIsPermissionGranted;
@@ -65,6 +74,7 @@ protected void onCreate(Bundle savedInstanceState) {
6574
mGLView = new TangoRajawaliView(this);
6675
mRenderer = new AugmentedRealityRenderer(this);
6776
mGLView.setSurfaceRenderer(mRenderer);
77+
mGLView.setOnTouchListener(this);
6878
mTango = new Tango(this);
6979
startActivityForResult(
7080
Tango.getRequestPermissionIntent(Tango.PERMISSIONTYPE_MOTION_TRACKING),
@@ -91,17 +101,17 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
91101
// Augmented reality view and renderer
92102
private void startAugmentedreality() {
93103
if (!mIsConnected) {
104+
mIsConnected = true;
94105
// Connect to color camera
95-
mGLView.connectToTangoCamera(mTango,
96-
TangoCameraIntrinsics.TANGO_CAMERA_COLOR);
106+
mGLView.connectToTangoCamera(mTango, TangoCameraIntrinsics.TANGO_CAMERA_COLOR);
97107

98108
// Use default configuration for Tango Service, plus low latency IMU integration.
99109
TangoConfig config = mTango.getConfig(TangoConfig.CONFIG_TYPE_DEFAULT);
100110
// NOTE: low latency integration is necessary to achieve a precise alignment of
101111
// virtual objects with the RBG image and produce a good AR effect.
102112
config.putBoolean(TangoConfig.KEY_BOOLEAN_LOWLATENCYIMUINTEGRATION, true);
113+
config.putBoolean(TangoConfig.KEY_BOOLEAN_DEPTH, true);
103114
mTango.connect(config);
104-
mIsConnected = true;
105115

106116
// No need to add any coordinate frame pairs since we are not using
107117
// pose data. So just initialize.
@@ -123,17 +133,55 @@ public void onFrameAvailable(int cameraId) {
123133

124134
@Override
125135
public void onXyzIjAvailable(TangoXyzIjData xyzIj) {
126-
// We are not using OnPoseAvailable for this app
136+
// Get the device pose at the time the point cloud was acquired
137+
TangoCoordinateFramePair framePair = new TangoCoordinateFramePair(
138+
TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE,
139+
TangoPoseData.COORDINATE_FRAME_DEVICE);
140+
TangoPoseData cloudPose = mTango.getPoseAtTime(xyzIj.timestamp, framePair);
141+
142+
// Save the cloud and point data for later use
143+
mPointCloudManager.updateXyzIjData(xyzIj, cloudPose);
127144
}
128145

129146
@Override
130147
public void onTangoEvent(TangoEvent event) {
131148
// We are not using OnPoseAvailable for this app
132149
}
133150
});
151+
152+
// Get extrinsics from device for use in transforms
153+
// This needs to be done after connecting Tango and listeners
154+
setupExtrinsics();
155+
156+
// Set-up point cloud plane fitting library helper class
157+
mPointCloudManager = new PointCloudManager(mTango.getCameraIntrinsics(
158+
TangoCameraIntrinsics.TANGO_CAMERA_COLOR));
159+
134160
}
135161
}
136162

163+
/**
164+
* Calculates and stores the fixed transformations between the device and the various sensors
165+
* to be used later for transformations between frames.
166+
*/
167+
private void setupExtrinsics() {
168+
// Create Camera to IMU Transform
169+
TangoCoordinateFramePair framePair = new TangoCoordinateFramePair();
170+
framePair.baseFrame = TangoPoseData.COORDINATE_FRAME_IMU;
171+
framePair.targetFrame = TangoPoseData.COORDINATE_FRAME_CAMERA_COLOR;
172+
TangoPoseData imuTrgbPose = mTango.getPoseAtTime(0.0, framePair);
173+
174+
// Create Device to IMU Transform
175+
framePair.targetFrame = TangoPoseData.COORDINATE_FRAME_DEVICE;
176+
TangoPoseData imuTdevicePose = mTango.getPoseAtTime(0.0, framePair);
177+
178+
// Create Depth camera to IMU Transform
179+
framePair.targetFrame = TangoPoseData.COORDINATE_FRAME_CAMERA_DEPTH;
180+
TangoPoseData imuTdepthPose = mTango.getPoseAtTime(0.0, framePair);
181+
182+
mRenderer.setupExtrinsics(imuTdevicePose, imuTrgbPose, imuTdepthPose);
183+
}
184+
137185

138186
@Override
139187
protected void onPause() {
@@ -152,4 +200,38 @@ protected void onResume() {
152200
startAugmentedreality();
153201
}
154202
}
203+
204+
@Override
205+
public boolean onTouch(View view, MotionEvent motionEvent) {
206+
if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
207+
// Calculate click location in u,v (0;1) coordinates
208+
float u = motionEvent.getX() / view.getWidth();
209+
float v = motionEvent.getY() / view.getHeight();
210+
211+
try {
212+
doFitPlane(u, v);
213+
} catch (Throwable t) {
214+
Log.e(TAG, "Exception measuring nomral", t);
215+
}
216+
}
217+
return true;
218+
}
219+
220+
/**
221+
* Use the TangoSupport library with point cloud data to calculate the plane of
222+
* the world feature pointed at the location the camera is looking at and update the
223+
* renderer to show a 3D object in that location.
224+
*/
225+
private void doFitPlane(float u, float v) {
226+
// Get the current device pose
227+
TangoCoordinateFramePair framePair = new TangoCoordinateFramePair(
228+
TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE,
229+
TangoPoseData.COORDINATE_FRAME_DEVICE);
230+
TangoPoseData devicePose = mTango.getPoseAtTime(0.0, framePair);
231+
232+
// Perform plane fitting with the latest available point cloud data
233+
TangoSupport.IntersectionPointPlaneModelPair planeModel =
234+
mPointCloudManager.fitPlane(u, v, devicePose, mRenderer.getPoseCalculator());
235+
mRenderer.updateObjectPose(planeModel.intersectionPoint, planeModel.planeModel, devicePose);
236+
}
155237
}

AugmentedRealitySample/app/src/main/java/com/projecttango/experiments/augmentedrealitysample/AugmentedRealityRenderer.java

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,19 @@
1818
import android.content.Context;
1919
import android.view.MotionEvent;
2020

21+
import com.google.atap.tangoservice.TangoPoseData;
22+
import com.projecttango.rajawali.Pose;
23+
import com.projecttango.rajawali.ScenePoseCalcuator;
2124
import com.projecttango.rajawali.ar.TangoRajawaliRenderer;
2225

2326
import org.rajawali3d.Object3D;
2427
import org.rajawali3d.lights.DirectionalLight;
2528
import org.rajawali3d.materials.Material;
2629
import org.rajawali3d.materials.methods.DiffuseMethod;
27-
import org.rajawali3d.primitives.NPrism;
28-
import org.rajawali3d.primitives.Sphere;
30+
import org.rajawali3d.materials.textures.ATexture;
31+
import org.rajawali3d.materials.textures.Texture;
32+
import org.rajawali3d.math.vector.Vector3;
33+
import org.rajawali3d.primitives.Cube;
2934

3035
/**
3136
* Very simple example augmented reality renderer which displays two objects in a fixed position
@@ -39,6 +44,13 @@
3944
*/
4045
public class AugmentedRealityRenderer extends TangoRajawaliRenderer {
4146

47+
private static final float CUBE_SIDE_LENGTH = 0.5f;
48+
49+
private Pose mPlanePose;
50+
private boolean mPlanePoseUpdated = false;
51+
52+
private Object3D mObject;
53+
4254
public AugmentedRealityRenderer(Context context) {
4355
super(context);
4456
}
@@ -55,23 +67,61 @@ protected void initScene() {
5567
light.setPosition(3, 2, 4);
5668
getCurrentScene().addLight(light);
5769

58-
// Set-up a material: green with application of the light
70+
// Set-up a material: green with application of the light and instructions
5971
Material material = new Material();
6072
material.setColor(0xff009900);
73+
try {
74+
Texture t = new Texture("instructions", R.drawable.instructions);
75+
material.addTexture(t);
76+
} catch (ATexture.TextureException e) {
77+
e.printStackTrace();
78+
}
79+
material.setColorInfluence(0.1f);
6180
material.enableLighting(true);
6281
material.setDiffuseMethod(new DiffuseMethod.Lambert());
6382

64-
// Build a pyramid and place it roughly in front and a bit to the right
65-
Object3D object1 = new NPrism(4, 0f, 0.2f, 0.2f);
66-
object1.setMaterial(material);
67-
object1.setPosition(-0.25, 0, -1);
68-
getCurrentScene().addChild(object1);
69-
70-
// Build a sphere and place it roughly in front and a bit to the left
71-
object1 = new Sphere(0.1f, 24, 24);
72-
object1.setMaterial(material);
73-
object1.setPosition(0.25, 0, -1);
74-
getCurrentScene().addChild(object1);
83+
// Build a Cube and place it initially in the origin
84+
mObject = new Cube(CUBE_SIDE_LENGTH);
85+
mObject.setMaterial(material);
86+
mObject.setPosition(0, 0, -3);
87+
mObject.setRotation(Vector3.Axis.Z, 180);
88+
getCurrentScene().addChild(mObject);
89+
}
90+
91+
@Override
92+
protected void onRender(long ellapsedRealtime, double deltaTime) {
93+
super.onRender(ellapsedRealtime, deltaTime);
94+
95+
synchronized (this) {
96+
if (mPlanePoseUpdated == true) {
97+
mPlanePoseUpdated = false;
98+
// Place the 3D object in the location of the detected plane
99+
mObject.setPosition(mPlanePose.getPosition());
100+
mObject.setOrientation(mPlanePose.getOrientation());
101+
// Move it forward by half of the size of the cube to make it flush with the plane
102+
// surface
103+
mObject.moveForward(CUBE_SIDE_LENGTH / 2.0f);
104+
}
105+
}
106+
}
107+
108+
/**
109+
* Update the 3D object based on the provided measurement point, normal (in depth frame) and
110+
* device pose at the time of measurement.
111+
*/
112+
public synchronized void updateObjectPose(double[] point, double[] normal,
113+
TangoPoseData devicePose) {
114+
mPlanePose = mScenePoseCalcuator.planeFitToOpenGLPose(point, normal, devicePose);
115+
mPlanePoseUpdated = true;
116+
}
117+
118+
/**
119+
* Provide access to scene calculator helper class to perform necessary transformations.
120+
* NOTE: This won't be necessary once transformation functions are available through the
121+
* support library
122+
*/
123+
public ScenePoseCalcuator getPoseCalculator() {
124+
return mScenePoseCalcuator;
75125
}
76126

77127
@Override
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright 2014 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.projecttango.experiments.augmentedrealitysample;
17+
18+
import com.google.atap.tangoservice.TangoCameraIntrinsics;
19+
import com.google.atap.tangoservice.TangoPoseData;
20+
import com.google.atap.tangoservice.TangoXyzIjData;
21+
import com.projecttango.rajawali.ScenePoseCalcuator;
22+
import com.projecttango.tangosupport.TangoSupport;
23+
24+
import java.nio.ByteBuffer;
25+
import java.nio.ByteOrder;
26+
27+
/**
28+
* This helper class keeps a copy of the point cloud data received in callbacks for use with the
29+
* plane fitting function.
30+
* It is implemented to be thread safe so that the caller (the Activity) doesn't need to worry
31+
* about locking between the Tango callback and UI threads.
32+
*/
33+
public class PointCloudManager {
34+
private static final String TAG = "PointCloudManager";
35+
36+
private final TangoCameraIntrinsics mTangoCameraIntrinsics;
37+
private final TangoXyzIjData mXyzIjData;
38+
private TangoPoseData mDevicePoseAtCloudTime;
39+
40+
public PointCloudManager(TangoCameraIntrinsics intrinsics) {
41+
mXyzIjData = new TangoXyzIjData();
42+
mTangoCameraIntrinsics = intrinsics;
43+
}
44+
45+
/**
46+
* Update the current cloud data with the provided xyzIjData from a Tango callback.
47+
*
48+
* @param from The point cloud data
49+
* @param xyzIjPose The device pose with respect to start of service at the time
50+
* the point cloud was acquired
51+
*/
52+
public synchronized void updateXyzIjData(TangoXyzIjData from, TangoPoseData xyzIjPose) {
53+
mDevicePoseAtCloudTime = xyzIjPose;
54+
55+
if (mXyzIjData.xyz == null || mXyzIjData.xyz.capacity() < from.xyzCount * 3) {
56+
mXyzIjData.xyz = ByteBuffer.allocateDirect(from.xyzCount * 3 * 4)
57+
.order(ByteOrder.nativeOrder()).asFloatBuffer();
58+
} else {
59+
mXyzIjData.xyz.rewind();
60+
}
61+
62+
mXyzIjData.xyzCount = from.xyzCount;
63+
mXyzIjData.timestamp = from.timestamp;
64+
65+
from.xyz.rewind();
66+
mXyzIjData.xyz.put(from.xyz);
67+
mXyzIjData.xyz.rewind();
68+
from.xyz.rewind();
69+
}
70+
71+
/**
72+
* Calculate the plane that best fits the current point cloud at the provided u,v coordinates
73+
* in the 2D projection of the point cloud data (i.e.: point cloud image).
74+
*
75+
* @param u u (horizontal) component of the click location
76+
* @param v v (vertical) component of the click location
77+
* @param devicePoseAtClickTime Device pose at the time this operation is requested
78+
* @param poseCalcuator ScenePoseCalculator helper instance to calculate transforms
79+
* @return The point and plane model, in depth sensor frame
80+
*/
81+
public synchronized TangoSupport.IntersectionPointPlaneModelPair fitPlane(float u, float v,
82+
TangoPoseData devicePoseAtClickTime, ScenePoseCalcuator poseCalcuator) {
83+
84+
// We need to calculate the transform between the color camera at the time the user clicked
85+
// and the depth camera at the time the depth cloud was acquired.
86+
// This operation is currently implemented in the provided ScenePoseCalculator helper
87+
// class. In the future, the support library will provide a method for this calculation.
88+
TangoPoseData colorCameraTDepthCameraWithTime
89+
= poseCalcuator.calculateColorCameraTDepthWithTime(devicePoseAtClickTime, mDevicePoseAtCloudTime);
90+
91+
return TangoSupport.fitPlaneModelNearClick(mXyzIjData, mTangoCameraIntrinsics,
92+
colorCameraTDepthCameraWithTime, u, v);
93+
}
94+
}
8.21 KB
Loading

0 commit comments

Comments
 (0)