1 package com.introlab.rtabmap;
3 import java.nio.ByteBuffer;
4 import java.nio.FloatBuffer;
5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.EnumSet;
9 import java.util.concurrent.atomic.AtomicBoolean;
11 import com.google.ar.core.Camera;
12 import com.google.ar.core.CameraIntrinsics;
13 import com.google.ar.core.Config;
14 import com.google.ar.core.Frame;
15 import com.google.ar.core.ImageMetadata;
16 import com.google.ar.core.PointCloud;
17 import com.google.ar.core.Pose;
18 import com.google.ar.core.Session;
19 import com.google.ar.core.SharedCamera;
20 import com.google.ar.core.TrackingState;
21 import com.google.ar.core.exceptions.CameraNotAvailableException;
22 import com.google.ar.core.exceptions.NotYetAvailableException;
23 import com.google.ar.core.exceptions.UnavailableException;
25 import android.content.Context;
26 import android.graphics.ImageFormat;
27 import android.hardware.camera2.CameraAccessException;
28 import android.hardware.camera2.CameraCaptureSession;
29 import android.hardware.camera2.CameraCharacteristics;
30 import android.hardware.camera2.CameraDevice;
31 import android.hardware.camera2.CameraManager;
32 import android.hardware.camera2.CaptureFailure;
33 import android.hardware.camera2.CaptureRequest;
34 import android.hardware.camera2.TotalCaptureResult;
35 import android.media.Image;
36 import android.opengl.GLES20;
37 import android.opengl.GLSurfaceView;
38 import android.os.Handler;
39 import android.os.HandlerThread;
40 import android.support.annotation.NonNull;
41 import android.util.Log;
42 import android.view.Surface;
85 private AtomicBoolean
mReady =
new AtomicBoolean(
false);
100 new CameraDevice.StateCallback() {
102 public void onOpened(@NonNull CameraDevice cameraDevice) {
103 Log.d(TAG,
"Camera device ID " + cameraDevice.getId() +
" opened.");
109 public void onClosed(@NonNull CameraDevice cameraDevice) {
110 Log.d(TAG,
"Camera device ID " + cameraDevice.getId() +
" closed.");
115 public void onDisconnected(@NonNull CameraDevice cameraDevice) {
116 Log.w(TAG,
"Camera device ID " + cameraDevice.getId() +
" disconnected.");
117 cameraDevice.close();
122 public void onError(@NonNull CameraDevice cameraDevice,
int error) {
123 Log.e(TAG,
"Camera device ID " + cameraDevice.getId() +
" error " + error);
124 cameraDevice.close();
130 CameraCaptureSession.StateCallback cameraCaptureCallback =
131 new CameraCaptureSession.StateCallback() {
136 public void onConfigured(@NonNull CameraCaptureSession session) {
137 Log.d(TAG,
"Camera capture session configured.");
138 captureSession = session;
143 public void onSurfacePrepared(
144 @NonNull CameraCaptureSession session, @NonNull Surface surface) {
145 Log.d(TAG,
"Camera capture surface prepared.");
149 public void onReady(@NonNull CameraCaptureSession session) {
150 Log.d(TAG,
"Camera capture session ready.");
154 public void onActive(@NonNull CameraCaptureSession session) {
155 Log.d(TAG,
"Camera capture session active.");
160 public void onClosed(@NonNull CameraCaptureSession session) {
161 Log.d(TAG,
"Camera capture session closed.");
165 public void onConfigureFailed(@NonNull CameraCaptureSession session) {
166 Log.e(TAG,
"Failed to configure camera capture session.");
172 new CameraCaptureSession.CaptureCallback() {
175 public void onCaptureCompleted(
176 @NonNull CameraCaptureSession session,
177 @NonNull CaptureRequest request,
178 @NonNull TotalCaptureResult result) {
179 Log.i(TAG,
"onCaptureCompleted");
183 public void onCaptureBufferLost(
184 @NonNull CameraCaptureSession session,
185 @NonNull CaptureRequest request,
186 @NonNull Surface target,
188 Log.e(TAG,
"onCaptureBufferLost: " + frameNumber);
192 public void onCaptureFailed(
193 @NonNull CameraCaptureSession session,
194 @NonNull CaptureRequest request,
195 @NonNull CaptureFailure failure) {
196 Log.e(TAG,
"onCaptureFailed: " + failure.getFrameNumber() +
" " + failure.getReason());
200 public void onCaptureSequenceAborted(
201 @NonNull CameraCaptureSession session,
int sequenceId) {
202 Log.e(TAG,
"onCaptureSequenceAborted: " + sequenceId +
" " + session);
209 if (sharedSession == null) {
214 Log.i(TAG,
"Resume ARCore.");
216 sharedSession.resume();
219 }
catch (CameraNotAvailableException
e) {
220 Log.e(TAG,
"Failed to resume ARCore session", e);
231 captureSession.setRepeatingRequest(
233 }
catch (CameraAccessException
e) {
234 Log.e(TAG,
"Failed to set repeating request", e);
240 Log.e(TAG,
"createCameraPreviewSession: " +
"starting camera preview session.");
243 sharedSession.setCameraTextureName(cameraTextureId);
249 List<Surface> surfaceList = sharedCamera.getArCoreSurfaces();
250 Log.e(TAG,
" createCameraPreviewSession: " +
"surfaceList: sharedCamera.getArCoreSurfaces(): " + surfaceList.size());
254 if (mTOFAvailable) surfaceList.add(mTOFImageReader.
imageReader.getSurface());
261 for (Surface surface : surfaceList) {
266 CameraCaptureSession.StateCallback wrappedCallback = sharedCamera.createARSessionStateCallback(cameraCaptureCallback, backgroundHandler);
269 cameraDevice.createCaptureSession(surfaceList, wrappedCallback, backgroundHandler);
272 }
catch (CameraAccessException
e) {
273 Log.e(TAG,
"CameraAccessException", e);
281 backgroundThread =
new HandlerThread(
"sharedCameraBackground");
282 backgroundThread.start();
283 backgroundHandler =
new Handler(backgroundThread.getLooper());
289 if (backgroundThread != null) {
290 backgroundThread.quitSafely();
292 backgroundThread.join();
293 backgroundThread = null;
294 backgroundHandler = null;
295 }
catch (InterruptedException
e) {
296 Log.e(TAG,
"Interrupted while trying to join background handler thread", e);
311 mPreviousTime = System.currentTimeMillis();
313 if(cameraTextureId == -1)
315 int[] textures =
new int[1];
316 GLES20.glGenTextures(1, textures, 0);
317 cameraTextureId = textures[0];
320 Log.v(TAG +
" opencamera: ",
"Perform various checks, then open camera device and create CPU image reader.");
322 if (cameraDevice != null) {
326 if (sharedSession == null) {
329 sharedSession =
new Session(mActivity, EnumSet.of(Session.Feature.SHARED_CAMERA));
330 }
catch (UnavailableException
e) {
331 Log.e(TAG,
"Failed to create ARCore session that supports camera sharing", e);
336 Config
config = sharedSession.getConfig();
337 config.setFocusMode(Config.FocusMode.FIXED);
338 config.setUpdateMode(Config.UpdateMode.LATEST_CAMERA_IMAGE);
339 config.setPlaneFindingMode(Config.PlaneFindingMode.DISABLED);
340 config.setLightEstimationMode(Config.LightEstimationMode.DISABLED);
342 sharedSession.configure(config);
347 sharedCamera = sharedSession.getSharedCamera();
349 cameraId = sharedSession.getCameraConfig().getCameraId();
351 ArrayList<String> resolutions;
353 mTOFAvailable =
false;
355 resolutions =
getResolutions(mActivity, cameraId, ImageFormat.DEPTH16);
356 if (resolutions != null) {
357 for( String temp : resolutions) {
358 Log.e(TAG +
"DEPTH16 resolution: ", temp);
360 if (resolutions.size()>0) mTOFAvailable =
true;
371 sharedCamera.setAppSurfaces(this.cameraId, Arrays.asList(mTOFImageReader.
imageReader.getSurface()));
377 CameraDevice.StateCallback wrappedCallback = sharedCamera.createARDeviceStateCallback(
cameraDeviceCallback, backgroundHandler);
380 cameraManager = (CameraManager) mActivity.getSystemService(Context.CAMERA_SERVICE);
386 cameraManager.openCamera(cameraId, wrappedCallback, backgroundHandler);
388 }
catch (CameraAccessException
e) {
389 Log.e(TAG,
"Failed to open camera", e);
391 }
catch (IllegalArgumentException e) {
392 Log.e(TAG,
"Failed to open camera", e);
394 }
catch (SecurityException e) {
395 Log.e(TAG,
"Failed to open camera", e);
399 Log.i(TAG,
" opencamera: TOF_available: " + mTOFAvailable);
407 if (sharedSession != null) {
408 sharedSession.pause();
411 if (captureSession != null) {
412 captureSession.close();
413 captureSession = null;
415 if (cameraDevice != null) {
416 cameraDevice.close();
424 if(cameraTextureId>=0)
426 GLES20.glDeleteTextures(1,
new int[] {cameraTextureId}, 0);
435 public void updateGL() throws CameraNotAvailableException {
442 if (mTOFAvailable && mTOFImageReader.
frameCount == 0)
return;
447 frame = sharedSession.update();
448 }
catch (Exception
e) {
453 Camera camera = null;
455 camera = frame.getCamera();
461 if (camera == null)
return;
463 if (camera.getTrackingState() == TrackingState.PAUSED)
return;
465 if (frame.getTimestamp() != 0) {
467 Pose pose = camera.getPose();
468 if(!
RTABMapActivity.
DISABLE_LOG) Log.d(TAG, String.format(
"pose=%f %f %f q=%f %f %f %f", pose.tx(), pose.ty(), pose.tz(), pose.qx(), pose.qy(), pose.qz(), pose.qw()));
472 if(System. currentTimeMillis() - mPreviousTime < rateMs)
476 mPreviousTime = System. currentTimeMillis();
478 CameraIntrinsics intrinsics = camera.getImageIntrinsics();
480 Image image = frame.acquireCameraImage();
481 PointCloud cloud = frame.acquirePointCloud();
482 FloatBuffer points = cloud.getPoints();
484 if (image.getFormat() != ImageFormat.YUV_420_888) {
485 throw new IllegalArgumentException(
486 "Expected image in YUV_420_888 format, got format " + image.getFormat());
491 for(
int i =0;i<image.getPlanes().length;++i)
493 Log.d(TAG, String.format(
"Plane[%d] pixel stride = %d, row stride = %d", i, image.getPlanes()[i].getPixelStride(), image.getPlanes()[i].getRowStride()));
497 float[] fl = intrinsics.getFocalLength();
498 float[] pp = intrinsics.getPrincipalPoint();
501 ByteBuffer y = image.getPlanes()[0].getBuffer().asReadOnlyBuffer();
502 ByteBuffer u = image.getPlanes()[1].getBuffer().asReadOnlyBuffer();
503 ByteBuffer v = image.getPlanes()[2].getBuffer().asReadOnlyBuffer();
505 double stamp = (double)image.getTimestamp()/10e8;
507 image.getWidth(), image.getHeight(), y.limit(), image.getFormat(), stamp));
516 pose.tx(), pose.ty(), pose.tz(), pose.qx(), pose.qy(), pose.qz(), pose.qw(),
517 fl[0], fl[1], pp[0], pp[1], stamp,
518 y, u, v, y.limit(), image.getWidth(), image.getHeight(), image.getFormat(),
520 points, points.limit()/4);
524 ByteBuffer bb = ByteBuffer.allocate(0);
527 pose.tx(), pose.ty(), pose.tz(), pose.qx(), pose.qy(), pose.qz(), pose.qw(),
528 fl[0], fl[1], pp[0], pp[1], stamp,
529 y, u, v, y.limit(), image.getWidth(), image.getHeight(), image.getFormat(),
530 bb, 0, 0, 0, ImageFormat.DEPTH16,
531 points, points.limit()/4);
537 }
catch (NotYetAvailableException e) {
548 public ArrayList<String>
getResolutions (Context context, String cameraId,
int imageFormat){
549 Log.v(TAG +
"getResolutions:",
" cameraId:" + cameraId +
" imageFormat: " + imageFormat);
551 ArrayList<String> output =
new ArrayList<String>();
553 CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
554 CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
556 for (android.util.Size s : characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(imageFormat)) {
557 output.add(s.getWidth() +
"x" + s.getHeight());
559 }
catch (Exception
e) {
566 public void initCamera (Context context, String cameraId,
int index){
570 CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
571 CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
572 for (android.util.Size s : characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(ImageFormat.DEPTH16)) {
574 if (current == index)
579 }
catch (Exception
e) {
583 Log.e(TAG +
" initCamera",
"Depth sensor not found!");
CaptureRequest.Builder previewCaptureRequestBuilder
void stopBackgroundThread()
static boolean DISABLE_LOG
void createCameraPreviewSession()
void startBackgroundThread()
HandlerThread backgroundThread
static final int DEPTH_HEIGHT
CameraCaptureSession captureSession
GLM_FUNC_DECL genType e()
CameraDevice cameraDevice
boolean isDepthSupported()
final CameraDevice.StateCallback cameraDeviceCallback
CameraManager cameraManager
static native void postCameraPoseEvent(long nativeApplication, float x, float y, float z, float qx, float qy, float qz, float qw)
static long nativeApplication
final CameraCaptureSession.CaptureCallback captureSessionCallback
ArrayList< String > getResolutions(Context context, String cameraId, int imageFormat)
GLSurfaceView surfaceView
static native void postOdometryEvent(long nativeApplication, float x, float y, float z, float qx, float qy, float qz, float qw, float fx, float fy, float cx, float cy, double stamp, ByteBuffer yPlane, ByteBuffer uPlane, ByteBuffer vPlane, int yPlaneLen, int rgbWidth, int rgbHeight, int rgbFormat, ByteBuffer depth, int depthLen, int depthWidth, int depthHeight, int depthFormat, FloatBuffer points, int pointsLen)
Handler backgroundHandler
void setRepeatingCaptureRequest()
ARCoreSharedCamera(RTABMapActivity c)
void startBackgroundThread()
void stopBackgroundThread()
void createImageReader(int width, int height)
SharedCamera sharedCamera
void initCamera(Context context, String cameraId, int index)
static RTABMapActivity mActivity
static final int DEPTH_WIDTH
TOF_ImageReader mTOFImageReader