Hi everyone,
I’m using a Pixhawk with ArduSub installed. My goal is to operate the vehicle in Depth Hold mode and keep it exactly at 1 meter depth. However, the vehicle consistently stabilizes at the bottom of a 2-meter pool, even though the target depth is set to 1.0 meter in the code.
Below is the full Python code I’m using. I’m sending a target depth via set_position_target_local_ned_send()
and switching to ALT_HOLD mode (which I understand corresponds to Depth Hold in ArduSub).
I don’t use a joystick because the system needs to be fully autonomous. According to the ArduSub documentation, Depth Hold mode maintains the current depth unless a manual dive/surface command is given. What I’m unsure about is whether this mode supports external depth targeting or not.
Here’s the full code:
#!/usr/bin/env python3
# -- coding: utf-8 --
from pymavlink import mavutil
import time
time.sleep(15)
TARGET_DEPTH = 1.0 # meters
P0 = None # surface pressure reference
last_send_time = 0
print("Connecting to Pixhawk...")
master = mavutil.mavlink_connection('/dev/ttyACM0', baud=57600)
master.wait_heartbeat()
print("Connected.")
def arm_vehicle():
master.mav.command_long_send(
master.target_system,
master.target_component,
mavutil.mavlink.MAV_CMD_COMPONENT_ARM_DISARM,
0,
1, 0, 0, 0, 0, 0, 0
)
print("ARM command sent.")
def set_alt_hold_mode():
master.mav.set_mode_send(
master.target_system,
mavutil.mavlink.MAV_MODE_FLAG_CUSTOM_MODE_ENABLED,
2 # ALT_HOLD
)
print("ALT_HOLD mode set.")
def calculate_depth(p_hPa, P0_hPa):
rho = 997.0
g = 9.80665
delta_p = (p_hPa - P0_hPa) * 100 # Convert to Pa
h = delta_p / (rho * g)
return max(0.0, h)
def send_target_depth(target_depth):
target_z = target_depth # In NED: positive Z is downward
master.mav.set_position_target_local_ned_send(
int(time.time() * 1000),
master.target_system,
master.target_component,
mavutil.mavlink.MAV_FRAME_LOCAL_NED,
0b0000111111111000, # Only position control
0, 0, target_z,
0, 0, 0,
0, 0, 0,
0, 0
)
print(f"Target depth sent: {target_depth:.2f} m")
arm_vehicle()
time.sleep(1)
set_alt_hold_mode()
time.sleep(1)
print("Reading pressure and calculating depth...")
while True:
msg = master.recv_match(type='SCALED_PRESSURE2', blocking=False)
if msg and msg.press_abs > 0:
pressure = msg.press_abs
if P0 is None:
P0 = pressure
print(f"Calibration complete: P0 = {P0:.2f} hPa")
continue
depth = calculate_depth(pressure, P0)
print(f"Current depth: {depth:.2f} m")
if time.time() - last_send_time > 1.0:
send_target_depth(TARGET_DEPTH)
last_send_time = time.time()
time.sleep(0.05)
Even though TARGET_DEPTH
is set to 1.0 meter, the vehicle always stabilizes at the pool floor (about 2 meters). So I’m wondering if the depth setpoint is being ignored because of how Depth Hold mode works.
This system must operate autonomously — so I cannot use a joystick to command the desired depth.
From the ArduSub documentation:
“In Depth Hold mode, the vehicle will maintain its current depth unless commanded to dive or surface. It will also maintain its current heading unless commanded otherwise.”
So, my question is:
Is it possible to set a specific target depth programmatically while in Depth Hold mode, or is this mode limited to holding the current depth only?
If this is not possible, what would be the recommended approach to hold a precise depth autonomously?
Also, I have a question about how Depth Hold mode works in QGroundControl:
If I switch to Depth Hold mode manually from the QGroundControl interface,
how does the vehicle determine which depth to hold?
Is it simply the current depth at the moment the mode is activated?
Is there any way to see or configure the target depth within QGroundControl itself?
I’ve read that in Depth Hold mode, the vehicle holds its depth unless a dive or surface command is given,
but I’d like to confirm if it always holds whatever depth it was at when entering the mode — and if so, how to verify or control that behavior more precisely?
Thanks