Capture geotagged image with Arducam 16mp autofoucus camera, Respberry pi 4 and Pixhawk

Hello, All. I’m new to DIY drones community
I built my first quadcopter using Pixhawk 2.4.8 and the Copter V4.2.1 firmware and I’m using a Raspberry Pi 4 as a companion computer.

My aspiration
I am willing to take geotaged photos with an Arducam camera connected to the RPi while completing a waypoint mission autonomously.

Following ae the hardware option available for me:

  1. Pixhawk 2.4.8
  2. Respberry pi 4
  3. Arducam 16mp autofocus

Objective:
Trigger Arducam automatically for taking geotagged photos while the drone is on a waypoint mission.

Is there any lead / solution that i can follow ?
Could some one please point me in right direction.
Thank you.

Hi Birendra,
It has been a while since applying these workflows, so there may be a error in my description of the process, but I think these are two approaches that may inform your efforts.
I think that you are wanting to create a mission using the survey grid tool. this will allow you to define the camera parameters to achieve the ground image you want. This tool will also allow for setting up the camera trigger for optimizing for 3D reconstruction (image sidelap and overlap. Camera triggers can be set as a high pin from one of the Autopilot output pins. You should, in theory, be able to trigger your Pi cam using this signal.
Alternatively you can set the camera trigger to a distance parameter and the signal will be sent at that interval or distance. I think this approach will work (if enabled) during a standard mission.
You can then use the geotagging tool in mission planner to correlate the cam messages to the images, creating a separate geotagged folder of the images.
Best of Luck,
Sean

2 Likes

Hi SeanHeadrick,

Thank you for the headsup, survey grid tool should work. Challage would be to automae it.
I will work on it and post the progress here.

Thank you

I was looking here for help with Lua scripting when I came upon your post. you might want to look into this as well for automating your process.https://ardupilot.org/copter/docs/common-lua-scripts.html

Thanks again, Every little information helps :slight_smile:

A few years ago I used an RPI+RPI camera to capture images as part of the TAP-J team’s entry in the Japan Innovation Challenge search and rescue competition. This included capturing the autopilot’s location and embedding it into JPEG images. The code we used is here (I think).

If you’re looking for a more robust solution there are some professional geotaggers on the AP wiki that work with sony cameras.

1 Like

After a lot of beating around the bush, I was able to capture the pictures and geotag them onboard.
Still had some issues in reading the gps data at the same time while triggering the camera and geotagging the images. I was also not sure about the accuracy. It would take a lot of effort to write fully optimised code for it.
Instead it would be easy and feasible to use Airpixel geotagger which has way more features than just geotagging, it is light weight, superfast etc, you can read about it in docs.

Hi Birendra

I’m working on pretty much exactly this but I’d like to trigger an array of arducams (ideally 5 in an oblique setup)

I was wondering if you could share your method and code on how you’ve done this?
I’m still a noob with this stuff but I’m slowly coming right haha.

Hi @Werner_Pretorius,

Assuming you have successful connection between Rpi and Pixhawk.
You can use below code as template, install python, exifread, dronekit.

import asyncio
import os
from datetime import datetime
import exifread
import dronekit
import time
import shutil

from picamera2 import Picamera2

# Define the target folder for geotagged images
TARGET_FOLDER = "/home/pi/Desktop/images/"


#1 Initialize PiCamera
picam2 = Picamera2()
#Create a new object, camera_config and use it to set the still image resolution (main) to 1920 x 1080. and a “lowres” image with a size of 640 x 480. This lowres image is used as the preview image when framing a shot.
camera_config = picam2.create_still_configuration(main={"size": (1920, 1080)}, lores={"size": (640, 480)}, display="lores")
#Load the configuration.
picam2.configure(camera_config)

#2 Connect to the drone and wait for GPS fix
print("Connecting to vehicle...")
vehicle = dronekit.connect('/dev/ttyAMA0', baud=57600)
print("Waiting for GPS fix...")
while not vehicle.gps_0.fix_type:
    pass
print("GPS fix obtained.")

# Define the capture_photo function
async def capture_photo():
    filename = datetime.now().strftime("%Y%m%d_%H%M%S.jpg")
    temp_file = "/run/shm/{}".format(filename) # Use the ramdisk for faster I/O
    picam2.start()
    #Pause the code for two seconds.
    time.sleep(1)
    #Capture an image and save it as test.jpg.
    picam2.capture_file(temp_file)
    return temp_file

# Define the get_gps_data function
async def get_gps_data():
    #return (vehicle.location.global_frame.lat,
     #       vehicle.location.global_frame.lon,
     #       vehicle.location.global_frame.alt)
     return(39.668756, -127.334674, 10)

# Define the geotag function
async def geotag(temp_file, gps_data):
    # gps_data should be a tuple containing latitude, longitude, and altitude
    latitude, longitude, altitude = gps_data
    
    # Construct the ExifTool command
    exiftool_cmd = ['exiftool', '-GPSLatitude={}'.format(latitude), '-GPSLongitude={}'.format(longitude), '-GPSAltitude={}'.format(altitude), temp_file]
    
    # Run the ExifTool command using subprocess
    try:
        subprocess.run(exiftool_cmd, check=True)
    except subprocess.CalledProcessError as e:
        print("Error geotagging photo: ", e)
        return False
    
    return True

# Define the main function
async def main():
    while True:
        # Wait for 5 seconds
        # Capture photo and get GPS data asynchronously
        temp_file_task = asyncio.create_task(capture_photo())
        gps_data_task = asyncio.create_task(get_gps_data())
        # Wait for both tasks to complete
        temp_file = await temp_file_task
        gps_data = await gps_data_task
        # Geotag the image asynchronously
        await geotag(temp_file, gps_data)

# Run the main function
asyncio.run(main())

In async def get_gps_data(): function you can use (I had used hard coded random value for testing)

gps_location = vehicle.location.global_relative
return(gps_location.lat, gps_location.lon, gps_location.alt))

You also you need to move geotagged image f(temp_file) to Target location of your choice…
You can add below code in async def geotag(temp_file, gps_data): function (inside try block)

shutil.move(temp_file, os.path.join(TARGET_FOLDER, filename))

For multiple camera you can use arducam multi camera adapter.
I hope this helps.

2 Likes

Also please read this in order to listen to the camera trigger signal from pixhawk and trigger the camera.from Rpi.