I've got a Starling Max 2 (VOXL2) connected to my home network. My laptop is also connected to that same network. I'm trying to connect to the drone using MAVSDK-Python but it just doesn't work. I've lost count of everything I've tried, nothing related to MAVSDK has worked for me.
I've updated the configuration file’s primary_static_gcs_ip
field at /etc/modalai/voxl-mavlink-server.conf
to my laptops IP address.
I'm able to connect with it using pymavlink
. I can adb shell
in and see the messages coming in by running voxl-inspect-mavlink mavlink_from_gcs
. But like I said, MAVSDK just does not connect to the VOXL2...
Here's an actual snippet I'm trying to run:
#!/usr/bin/env python3
import asyncio
import time
from mavsdk import System
from pymavlink import mavutil
async def send_heartbeat_and_param_requests(target_ip="192.168.1.187", target_port=14550):
"""Send MAVLink heartbeats and parameter requests to initiate connection with VOXL2"""
print(f"Sending heartbeats to {target_ip}:{target_port}")
# Create a UDP connection to VOXL2
connection = mavutil.mavlink_connection(f'udpout:{target_ip}:{target_port}')
# Important: Set specific system and component IDs
# System ID should not be 1 (typically the vehicle) or 255
# Component ID should NOT be 0 as that's invalid for a source
connection.source_system = 2 # Use 2 for a secondary GCS
connection.source_component = 1 # Use 1 for autopilot component
# Send heartbeats in a loop
counter = 0
while True:
# Send a heartbeat message
connection.mav.heartbeat_send(
mavutil.mavlink.MAV_TYPE_GCS, # Type: Ground Control Station
mavutil.mavlink.MAV_AUTOPILOT_INVALID, # Autopilot type
0, # Base mode
0, # Custom mode
mavutil.mavlink.MAV_STATE_ACTIVE # System status
)
counter += 1
if counter % 5 == 0: # Every 5 seconds
# Send a parameter request list (this is what QGC does on connection)
connection.mav.param_request_list_send(
1, # Target system (default autopilot is usually 1)
190 # Target component (default autopilot component)
)
# Send a ping message
connection.mav.ping_send(
int(time.time() * 1000), # Unix timestamp in milliseconds
0, # Sequence
connection.source_system, # System ID
connection.source_component # Component ID
)
print(f"Heartbeat sent (count: {counter})")
await asyncio.sleep(1) # Send heartbeats at 1Hz
async def connect_to_drone():
print("Connecting to VOXL2...")
drone = System()
# Different connection string formats to try
await drone.connect(system_address="udp://:14550")
print("Waiting for drone to connect...")
timeout = 60 # Extended timeout
start_time = asyncio.get_event_loop().time()
try:
async for state in drone.core.connection_state():
print(f"Connection state: {state}")
if state.is_connected:
print(f"Connected to drone!")
return drone
# Check if we've timed out
current_time = asyncio.get_event_loop().time()
if current_time - start_time > timeout:
print(f"Connection timed out after {timeout} seconds")
break
await asyncio.sleep(1)
except Exception as e:
print(f"Connection error: {e}")
return None
async def main():
# Start sending heartbeats in the background
heartbeat_task = asyncio.create_task(send_heartbeat_and_param_requests())
# Wait to ensure heartbeats are being received
await asyncio.sleep(5)
# Try to connect to the drone
drone = await connect_to_drone()
# If connected, do something with the drone
if drone and drone.core:
try:
# Print basic information
info = await drone.info.get_version()
print(f"Version Info: {info}")
except Exception as e:
print(f"Could not get info: {e}")
# Clean up the heartbeat task
heartbeat_task.cancel()
try:
await heartbeat_task
except asyncio.CancelledError:
print("Heartbeat task cancelled")
if __name__ == "__main__":
# Run the asyncio loop
asyncio.run(main())
It never even gets to print out the "Waiting for drone to connect..." mesage. The code doesn't execute past the await drone.connect(system_address="udp://:14550")
line.
For the await drone.connect(system_address="udp://:14550")
line I've tried every permutation I've found. With or without the VOXL2 IP address. I've used udpout
and all other variants, none work.
I've tried with and without sending the messages using pymavlink
in case there is some conflict.
I've tried connecting with specific sysid
and compid
like below:
# Create a System object with specific system ID and component ID
# These match the IDs we're using in the heartbeat sender
drone = System(sysid=2, compid=1)
I don't know what else to do. Any help will be greatly appreciated.