Burst images at way points

Hello All,

The Parrot Anafi looks like an exciting drone. I did some initial tests with Olympe and the flight simulator. The simulator was working for some basic motion. To do what I want though, I need to track motion of surface features with sequential images. I need to known the time between sequential images, the drone position, and the camera orientation …

so, I have two questions,

  1. Is it possible to program burst images at a way point and if so could you give a program example ?

  2. Do the image headers have info such as a) GPS position, b) drone attitude, c) camera attitude, and d) the time the image was collected (fractional second not just second).

many thanks
John

Hello John,

Yes, it’s possible! The following example demonstrate how to take a photo burst of 14 image in 1 second. Check the bust_value enum definition for other possible bust configuration) : 14 over 1/2/4 seconds, 10 over 1/2/4 seconds, and 4 over 1/2/4 seconds.

from olympe.messages.camera import (
    set_camera_mode,
    set_photo_mode,
    take_photo,
    photo_progress,
)
import olympe
import os
import re
import requests
import shutil
import tempfile
import xml.etree.ElementTree as ET


# Drone IP
ANAFI_IP = "192.168.42.1"

# Drone web server URL
ANAFI_URL = "http://{}/".format(ANAFI_IP)

# Drone media web API URL
ANAFI_MEDIA_API_URL = ANAFI_URL + "api/v1/media/medias/"

XMP_TAGS_OF_INTEREST = (
    "CameraRollDegree",
    "CameraPitchDegree",
    "CameraYawDegree",
    "CaptureTsUs",
    # NOTE: GPS metadata is only present if the drone has a GPS fix
    # (i.e. they won't be present indoor)
    "GPSLatitude",
    "GPSLongitude",
    "GPSAltitude",
)


def take_photo_burst(drone):
    # take a photo burst and get the associated media_id
    photo_saved = drone(photo_progress(result="photo_saved", _policy="wait"))
    drone(take_photo(cam_id=0)).wait()
    photo_saved.wait()
    media_id = photo_saved.received_events().last().args["media_id"]

    # download the photos associated with this media id
    media_info_response = requests.get(ANAFI_MEDIA_API_URL + media_id)
    media_info_response.raise_for_status()
    download_dir = tempfile.mkdtemp()
    for resource in media_info_response.json()["resources"]:
        image_response = requests.get(ANAFI_URL + resource["url"], stream=True)
        download_path = os.path.join(download_dir, resource["resource_id"])
        image_response.raise_for_status()
        with open(download_path, "wb") as image_file:
            shutil.copyfileobj(image_response.raw, image_file)

        # parse the xmp metadata
        with open(download_path, "rb") as image_file:
            image_data = image_file.read()
            image_xmp_start = image_data.find(b"<x:xmpmeta")
            image_xmp_end = image_data.find(b"</x:xmpmeta")
            image_xmp = ET.fromstring(image_data[image_xmp_start : image_xmp_end + 12])
            for image_meta in image_xmp[0][0]:
                xmp_tag = re.sub(r"{[^}]*}", "", image_meta.tag)
                xmp_value = image_meta.text
                # only print the XMP tags we are interested in
                if xmp_tag in XMP_TAGS_OF_INTEREST:
                    print(resource["resource_id"], xmp_tag, xmp_value)


def setup_photo_burst_mode(drone):
    drone(set_camera_mode(cam_id=0, value="photo")).wait()
    # For the file_format: jpeg is the only available option
    # dng is not supported in burst mode
    drone(
        set_photo_mode(
            cam_id=0,
            mode="burst",
            format="rectilinear",
            file_format="jpeg",
            burst="burst_14_over_1s",
            bracketing="preset_1ev",
            capture_interval=0.0,
        )
    ).wait()


def main(drone):
    drone.connection()
    setup_photo_burst_mode(drone)
    take_photo_burst(drone)


if __name__ == "__main__":
    with olympe.Drone(ANAFI_IP, loglevel=0) as drone:
        main(drone)

To go to a specific GPS coordinate before taking the burst images, you have to use the moveTo command. You should refer to the Moving around - Waiting for a ‘hovering’ flying state user guide section and use the moveTo command instead of the moveBy command.

The example above download the burst images with the drone web API and extract relevant XMP metadata : “CameraRollDegree”, “CameraPitchDegree”, “CameraYawDegree”, “CaptureTsUs”, “GPSLatitude”, “GPSLongitude” and “GPSAltitude”.

Note: GPS metadata is only present if the drone has a GPS fix (i.e. they won’t be present while the drone is indoor).

Regards
Nicolas