QGroundControl in parallel with Python Script using SITL Environment

I am currently trying to run QGroundControl and a python script at the same time to send basic commands to a SITL environment of the ArduSub simulation. My SITL is currently running on my desktop using WSL2 on Ubuntu version 22.04. To start the SITL I follow the recommended guide commands:

and I am able to connect with both QGroundControl and python just not at the same time. Checking the outputs on the MAVProxy command window shows 2 outputs:

I want to send commands through the 14551 port so I adjusted the vehicle_sim.py code line to read:

sim_vehicle.py -L RATBeach --out=udp: --out=udp: --map --console

which does add the extra output port on the MAVProxy. Then running a heartbeat python test on this line it does not return anything and is stuck at the line 9 as seen below:

I thought to resolve this would be simply to add a comm link in QGroundControl and to connect with it but that didn’t work:

I feel I am very close to resolving this issue but would like some quick assistance to get QGroundControl and python working in parallel. Can anyone explain the misunderstanding that I am having and point me towards getting my system communicating.

The older udp: prefix is a shortcut for the newer udpin: prefix, which sets up a server connection.

The option --out=udp: actually means: Create a socket, bind it to port 14551 on all interfaces, and wait for messages to arrive.

Since your Python script is also using udpin: they are both acting as servers waiting for messages to arrive.

Try this option on SITL: --out=udpout:

1 Like

Thanks for the reply Clyde!
So by making both receivers (udpin/udp) they will never receive the heartbeat on that port - changing one to a transmitter (udpout) will send the heartbeat.

I made a connection to in QGroundControl and the heartbeat can now be seen in python. My python script returns system 0 and component 0 - I expected system 1 and component 0. Why is there a difference?

It looks like you are trying to find the source of the HEARTBEAT message – for that you’ll need to get a reference to the message object. (the_connection is a reference to the connection object, not the message object.)

Try something like this:

from pymavlink import mavutil

conn = mavutil.mavlink_connection('udpin:')

heartbeats = {}

while True:
    # Wait for the next heartbeat
    message = conn.recv_match(type=['HEARTBEAT'], blocking=True)
    source_system = message.get_srcSystem()
    source_component = message.get_srcComponent()
    key = f'source_system={source_system}, source_component={source_component}'
    timestamp = getattr(message, '_timestamp', 0.0)
    if key not in heartbeats:
        print(f'Component found: {key}')
    heartbeats[key] = timestamp

Not exactly what I am trying to achieve - although thanks for that code I will keep it for later reference. I would like to control an ROV using python scripts while having my QGroundControl open at the same time. At the moment I am able to send commands to the SITL ROV using when QGC is closed, but when open it will not because 14550 is used by QGC. My python scripts are very basic at the moment so I can learn in steps and at the end I will make a more complex file later on.

When I added your suggest of –out=udpout: I was still not able to arm my ROV using:

the code will run until it try’s to validate the connection through the heartbeat but will not progress past that. My next question would be why did creating the output port on 14551 not show a heartbeat? Is it the way running the sim_vehicle.py initializes the MAVProxy GCS when we run the code:

Thanks for taking the time to assist with this I do appreciate it.

Did you try using udpin:0:0:0:0:14551 in your python script?

Also, I experienced some issues (with UDP connection, laggy git operations, slow compilation) when trying to run SITL using WSL2. If you want to continue making this work on WSL2 you want to read this: Accessing network applications with WSL | Microsoft Learn

However, you may also try switching back to WSL 1.

First display the name of your installed WSL Ubuntu version:

wsl --list --verbose


wsl --set-version <your-ubuntu-name> 1
1 Like

I originally did try with that udpin: but it would still wait for the heartbeat in .wait_hearbeat() and not progress. I am going to try to establish the connection and send the arm command without the .wait_heartbeat and see if I can arm the SITL environment.

Thanks for that article I’ll be sure to read up on it. Maybe WSL2 is the issue I am having and swapping back to WSL1 will be better for testing purposes. If there are any more suggestions from anyone please do post, I’ll try them out and update the post for anyone else starting out.