Real-time Drone Folium Maps Drones

How to Use

  • Run Cell 1:

    • This cell sets up the telemetry functions and initializes the CSV file.
  • Run Cell 2:

    • This cell runs the telemetry loop. It will continuously fetch telemetry data and update the map until you interrupt the cell execution (e.g., using the stop button in Jupyter).
  • Run Cell 3:

    • This cell displays the latest map. You can re-run this cell to refresh the map display with updated data.

Make a folium map of drone data

Setup and Telemetry Functions

In [ ]:
import csv
from pathlib import Path
import folium
import pandas as pd
from jinja2 import Template
from dronekit import connect
import time
import datetime
import os
import subprocess

# Function to start GStreamer
def start_gstreamer():
    gst_command = [
        r"C:\gstreamer\1.0\msvc_x86_64\bin\gst-launch-1.0.exe",
        "udpsrc", "port=5600", "buffer-size=524288",
        "!", "application/x-rtp", 
        "!", "rtpjitterbuffer", "latency=200",
        "!", "rtph264depay",
        "!", "avdec_h264",
        "!", "videoconvert",
        "!", "autovideosink"
    ]
    return subprocess.Popen(gst_command)

# Start GStreamer
gst_process = start_gstreamer()

# Connect to the drone's telemetry feed
vehicle = connect('udpin:192.168.0.144:14550', wait_ready=False)
vehicle.initialize(8, 30)
vehicle.wait_ready('autopilot_version')

telemetry_count = 0  # Initialize the counter

# Path for the CSV file
current_directory = Path.cwd()
subdirectory = 'Data'
data_directory = current_directory / subdirectory
data_directory.mkdir(exist_ok=True)
file_path = data_directory / 'drone_photos.csv'

# Initialize the CSV file
with open(file_path, 'w', newline='') as file:
    writer = csv.writer(file)
    writer.writerow(['latitude', 'longitude', 'photo', 'timestamp', 'description'])

def print_telemetry():
    """Prints the drone's telemetry data and updates the CSV file."""
    global telemetry_count
    telemetry_count += 1  # Increment the counter
    current_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')  # Get the current local time
    print(f'Telemetry Data Feed {telemetry_count} - Timestamp: {current_time}')
    print('Location global alt (feet): %s' % (vehicle.location.global_frame.alt * 3.281 if vehicle.location.global_frame.alt else None))
    print('Pitch: %s' % vehicle.attitude.pitch)
    print("Velocity: %s" % vehicle.velocity)
    print("GPS: %s" % vehicle.gps_0)
    print("Flight mode currently: %s" % vehicle.mode.name)
    print('Battery level: %s' % vehicle.battery.level)
    print('Status: %s' % vehicle.system_status.state)
    print('Armed: %s' % vehicle.armed)
    print('Heading: %s' % vehicle.heading)
    print('Speed: %s' % vehicle.groundspeed)
    print('GPS fix: %s' % vehicle.gps_0.fix_type)
    print('Satellites: %s' % vehicle.gps_0.satellites_visible)
    print('Location global lat: %s' % vehicle.location.global_frame.lat)
    print('Location global lon: %s' % vehicle.location.global_frame.lon)
    print('Groundspeed: %s' % vehicle.groundspeed)
    print('Velocity: %s' % vehicle.velocity[2])
    
    # Save telemetry data to a CSV file
    with open(file_path, 'a', newline='') as file:
        writer = csv.writer(file)
        writer.writerow([
            vehicle.location.global_frame.lat,
            vehicle.location.global_frame.lon,
            'photo.jpg',  # Placeholder for photo name
            current_time,
            f'Telemetry Data Feed {telemetry_count}'
        ])

def update_map():
    """Updates the Folium map with the latest telemetry data."""
    # Load the updated data
    data = pd.read_csv(file_path)

    # Create a map centered around the average coordinates
    map_center = [data['latitude'].mean(), data['longitude'].mean()]
    m = folium.Map(location=map_center, zoom_start=13)

    # Add markers with popups for each telemetry point
    for idx, row in data.iterrows():
        popup_html = f"""
        <strong>Description:</strong> {row['description']}<br>
        <strong>Timestamp:</strong> {row['timestamp']}<br>
        <img src='{row['photo']}' alt='Photo' width='200'>
        """
        folium.Marker([row['latitude'], row['longitude']], popup=popup_html).add_to(m)

    # Save the Folium map to a string
    folium_map = m._repr_html_()

    # Load the Jinja2 template
    template_html = """
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Drone Photos Map</title>
    </head>
    <body>
        {{ folium_map | safe }}
    </body>
    </html>
    """

    template = Template(template_html)
    rendered_html = template.render(folium_map=folium_map)

    # Save the rendered HTML to a file
    output_path = current_directory / 'map.html'
    with open(output_path, 'w') as f:
        f.write(rendered_html)
Running cells with 'venv (Python 3.11.1)' requires the ipykernel package.

Run the following command to install 'ipykernel' into the Python environment. 

Command: 'c:/Users/Brian/Desktop/Drone/TensorFlow_image_classifier/venv/Scripts/python.exe -m pip install ipykernel -U --force-reinstall'

Running the Telemetry Loop

In [ ]:
import time

exit_flag = False  # Flag to indicate whether to exit the main loop

# Continuously print telemetry data every 30 seconds until user interrupts
try:
    while not exit_flag:
        print_telemetry()
        update_map()
        
        # Wait for 30 seconds, but check for interruption
        for _ in range(30):
            if user_input in ['q', 'quit']:
                exit_flag = True
                break
            time.sleep(1)
except KeyboardInterrupt:
    exit_flag = True
finally:
    # Close the vehicle connection
    vehicle.close()
    print("Vehicle connection closed.")

Display the Map in Jupyter Notebook

In [ ]:
from IPython.display import IFrame
IFrame('map.html', width=700, height=600)

links

social