Programmatically Taking a Picture

Hello,

I am currently using Android Studio and the Kotlin programming language to code my Anafi drone to periodically take a picture and send that image along with some metadata off elsewhere. I was able to get metadata such as the drone’s GPS location, compass heading, and altitude from takeoff, but I have absolutely no clue on how to take a photo using the drone’s camera.

I was able to use the capture() command from GsdkStreamView to get the bitmap of the live stream, but the quality of the image is much lower than desired. As a result, I tried working with the Main Camera.

My approach right now is to instantiate a reference to the drone’s MainCamera, then create a method to monitor the main camera and configure its settings using it.photo()?.setFileFormat( … ) where “it” is a MainCamera object created by the lambda function used when monitoring the MainCamera.

To take an image, I was thinking of making a takePhoto() method, in which the startPhotoCapture() and stopPhotoCapture() methods are used, but I have absolutely no idea how to use them.

Can someone point me in the right direction or give some further clarification on how to take a picture with the drone?

Switch capture mode to photo
Start photo capture

And you’ll have a single photo stored on the drone (assuming defaults).

Stop photo capture is used when you have time/gps lapse active.

Thank you very much for the clarification. I could not find any mention in either the API documentation or the GitHub code of stopPhotoCapture only being necessary when time lapse or GPS lapse is set as the photo mode. That would have been very helpful to know.

Okay, so I’ve run into a couple problems with this. I was able to find how to configure most of the camera settings, such as making the photo mode SINGLE, photo format RECTILINEAR, and file format JPEG. I was able to find what you mentioned earlier about the capture modes being PHOTO and RECORDING, but I could not find out how to explicitly set that mode. The mode enum could be accessed by calling mode() on the Main Camera object, but I couldn’t set the mode in any way.

I’m not sure if this is a direct result of this ambiguity, but I attempted to use the startPhotoCapture() command, and it did not save any sort of image to the drone. Do you have any idea what went wrong in this case?

Sometimes it’s easier to just share code :slight_smile:

    cameraImage.setOnClickListener(view -> {
        final MainCamera camera = ardrone.getMainCamera();
        if (camera == null) return;

        if (camera.mode().getAvailableValues().contains(MainCamera.Mode.PHOTO)) {
            final MainCameraRefRunnable takePhotoRunnable = new MainCameraRefRunnable();

            takePhotoRunnable.setMainCameraRef(ardrone.getPeripheral(MainCamera.class, new Ref.Observer<MainCamera>() {
                private boolean posted;

                @Override
                public void onChanged(@Nullable MainCamera cam) {
                    if (cam != null && cam.mode().getValue() == MainCamera.Mode.PHOTO && !posted) {
                        if (cam.canStartPhotoCapture()) {
                            posted = true;
                            cam.startPhotoCapture();
                            new Handler().post(takePhotoRunnable);
                        } else if (cam.canStopPhotoCapture()) {
                            posted = true;
                            cam.stopPhotoCapture();
                            new Handler().post(takePhotoRunnable);
                        }
                    }
                }
            }));

            if (camera.mode().getValue() != MainCamera.Mode.PHOTO)
                camera.mode().setValue(MainCamera.Mode.PHOTO);
        }
    });

Hope this helps!

1 Like

For the sake of completeness, this is how I manage the Observer lifecycle with the runnable referenced above:

private static class MainCameraRefRunnable implements Runnable {
    private Ref<MainCamera> mainCameraRef = null;

    void setMainCameraRef(Ref<MainCamera> mainCameraRef) {
        this.mainCameraRef = mainCameraRef;
    }

    @Override
    public void run() {
        if (mainCameraRef != null) mainCameraRef.close();
    }
}
2 Likes

All this code helps a lot. I had to convert the code from Java to Kotlin, but I was able to do it and get a capture to occur periodically. Thanks a lot for the help here.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.