robotemi / sdk

temi is an unparalleled robotic platform introducing a new dimension of development - movement. Using temi’s SDK, developers can create new functionalities and introduce new use cases via temi’s Android tablet. temi’s movement and navigation capabilities run off of it's Linux computer and uses a set of 16 sensors including a Lidar, depth cameras, driving cameras, and microphones. We encourage our developer community to suggest and request expanded functionality within the SDK and we will adhere to your needs. We want to enable you to create skills like never seen before! We will be constantly improving the SDK and its documentation. Please feel free to reach out to us with any questions or thoughts at developers@robotemi.com
https://www.robotemi.com/
204 stars 87 forks source link

CameraX imageCapture.takepicture() doesn't seem to be working for Temi. #213

Open roberthobblebottom opened 3 years ago

roberthobblebottom commented 3 years ago

I kept getting these errors:

E/RequestThread-1: Hit timeout for jpeg callback!
W/CaptureCollector: Jpeg buffers dropped for request: 1
E/CameraDevice-JV-1: Lost output buffer reported for frame 270
W/LegacyRequestMapper: convertRequestMetadata - control.awbRegions setting is not supported, ignoring value
W/LegacyRequestMapper: Only received metering rectangles with weight 0.
    convertRequestToMetadata - Ignoring android.lens.focusDistance false, only 0.0f is supported
I/RequestThread-1: Received jpeg.
W/CaptureCollector: jpegProduced called with no jpeg request on queue!
E/RequestThread-1: Dropping jpeg frame.

While debugging, I never go into either onCaptureSuccess(), onImageSaved() or onError() when I am using the either two overloads of takePicture(). It is odd. Is this a programming error or limitations on Temi?

Main codes:

  private void setupCameraX() {
        ListenableFuture<ProcessCameraProvider> cameraProviderFuture =
                ProcessCameraProvider.getInstance(this);

        cameraProviderFuture.addListener(() -> {
            try {
                ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
                PreviewView previewView = findViewById(R.id.preview_view);
                final Preview preview = new Preview.Builder()
                        .build();
                CameraSelector cameraSelector = new CameraSelector
                        .Builder()
                        .requireLensFacing(CameraSelector.LENS_FACING_FRONT)
                        .build();
                preview.setSurfaceProvider(previewView.getSurfaceProvider());
                imageCapture = new ImageCapture
                        .Builder()
                        .setTargetRotation(Surface.ROTATION_270)
                        .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)

                        .build();

                cameraProvider.unbindAll();
                cameraProvider.bindToLifecycle(
                        this,
                        cameraSelector,
                        imageCapture,
                        preview);

                findViewById(R.id.imageCaptureButton).setOnClickListener(v -> {
                    this.captureAnImage();
                });
            } catch (InterruptedException | ExecutionException e) {
                new AlertDialog
                        .Builder(this)
                        .setTitle("Camera setup error")
                        .setMessage(e.getMessage())
                        .setPositiveButton("Ok",
                                (dialog, which) -> {
                                })
                        .show();
            }
        }, ContextCompat.getMainExecutor(this));

    }

    private void captureAnImage() {
//        Log.d("images URI",
//        "Path: " +   MediaStore.Images.Media.INTERNAL_CONTENT_URI.getPath());//not working?
        //TODO: get the path to use it for my bash script
        SimpleDateFormat formatter = (SimpleDateFormat) SimpleDateFormat.getDateTimeInstance();
        Date date = new Date();
        ContentValues contentValues = new ContentValues();
        contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME,
                "Fall Prevention Training Data " + formatter.format(date));
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH,
                    String.valueOf(this.getFilesDir()));
        }
        contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
        ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture
                .OutputFileOptions
//                .Builder(new File(this.getFilesDir(),
//                "trainingDate"+ formatter.format(date)+".jpg"))
                .Builder(getContentResolver(),
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                contentValues)
                .build();
//        imageCapture.takePicture(outputFileOptions,
//                executor,
//                new ImageCapture.OnImageSavedCallback() {
//                    @Override
//                    public void onImageSaved(
//                            @NotNull ImageCapture.OutputFileResults outputFileResults) {
//                        Log.d("imagePathname", "Path: " + outputFileResults.toString());
//                    }
//
//                    @Override
//                    public void onError(@NotNull ImageCaptureException exception) {
//                        exception.printStackTrace();
//                    }
//                });
        imageCapture.takePicture(ContextCompat.getMainExecutor(this), new ImageCapture.OnImageCapturedCallback() {
            @Override
            public void onCaptureSuccess(@NonNull @NotNull ImageProxy image) {
                super.onCaptureSuccess(image);
            }
        });
    }

AndroidManifest.xml `<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="org.FallPreventionAITrainingCamera">

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<uses-feature android:name="android.hardware.camera.any" />

<application
    android:allowBackup="false"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/Theme.FallDetectionAITrainingCamera"
    tools:ignore="AllowBackup">

    <meta-data
        android:name="com.robotemi.sdk.metadata.SKILL"
        android:value="@string/app_name" />

    <activity android:name="org.FallPreventionAITrainingCamera.MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>

        <!-- Register as a system camera app -->
        <intent-filter>
            <action android:name="android.media.action.IMAGE_CAPTURE" />
            <action android:name="android.media.action.STILL_IMAGE_CAMERA"/>
            <action android:name="android.media.action.VIDEO_CAMERA" />
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>
    </activity>
</application>

`

build.gradle

plugins {
    id 'com.android.application'
    id "net.ltgt.errorprone" version "2.0.1"

}
apply plugin: 'com.android.application'

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.3"

    defaultConfig {
        applicationId "org.FallDetectionAITrainingCamera"
        minSdkVersion 22
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

//        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.3.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'

    def camerax_version = "1.1.0-alpha06"
    implementation "androidx.camera:camera-core:$camerax_version"
    implementation "androidx.camera:camera-camera2:$camerax_version"
    implementation "androidx.camera:camera-lifecycle:${camerax_version}"
    implementation "androidx.camera:camera-view:1.0.0-alpha26"

    implementation "com.google.android.material:material:1.4.0"
    implementation "androidx.camera:camera-extensions:1.0.0-alpha26"

    annotationProcessor "com.uber.nullaway:nullaway:0.9.1"
    errorprone 'com.google.errorprone:error_prone_core:2.5.1'
    errorproneJavac 'com.google.errorprone:javac:9-dev-r4023-3'

    implementation 'com.robotemi:sdk:0.10.77'
}

//code below is bugged (info: https://youtrack.jetbrains.com/issue/IDEA-230155)
//import net.ltgt.gradle.errorprone.CheckSeverity
//you can ignore the error, it will still work
import net.ltgt.gradle.errorprone.*

tasks.withType(JavaCompile) {
    // remove the if condition if you want to run NullAway on test code
    if (!name.toLowerCase().contains("test")) {
        options.errorprone {
            check("NullAway", CheckSeverity.ERROR)
            option("NullAway:AnnotatedPackages", "com.uber")
        }
    }
}
zjn0505 commented 3 years ago

Sorry I haven't ran your code. I just ran the sample code in https://github.com/android/camera-samples/tree/master/CameraXBasic and installed the temi mobile app which uses CameraX. Both look o.k.

Is your firmware 20201216.154352? This can be found in Settings -> About.

roberthobblebottom commented 3 years ago

Yes, that is my firmware number!

stawberryslayer commented 2 months ago

Hi I am wondering how do you resolve the issue in the end? I got the same issue, the preview look fine, but I am not able to take a picture