How to Control Drone Using PX4 Offboard Mode
To control a drone using
PX4 offboard mode, you send position, velocity, or attitude setpoints from an external computer or companion computer to the flight controller via MAVLink. You must first enable offboard mode, then continuously stream commands at a steady rate to maintain control.Syntax
In PX4 offboard mode, you typically send commands using MAVLink messages such as SET_POSITION_TARGET_LOCAL_NED or SET_ATTITUDE_TARGET. The main steps are:
- Enable offboard mode: Switch the drone's flight mode to offboard.
- Send setpoints: Continuously send position, velocity, or attitude targets.
- Maintain rate: Commands must be sent at about 10 Hz or faster to keep control.
c
mavlink_message_t msg; // Example: Set position target in local NED frame mavlink_set_position_target_local_ned_t sp; sp.time_boot_ms = current_time_ms(); sp.coordinate_frame = MAV_FRAME_LOCAL_NED; sp.type_mask = POSITION_TARGET_TYPEMASK_VX_IGNORE | POSITION_TARGET_TYPEMASK_VY_IGNORE | POSITION_TARGET_TYPEMASK_VZ_IGNORE; sp.x = 0; // desired x position in meters sp.y = 0; // desired y position in meters sp.z = -5; // desired altitude (negative down) mavlink_msg_set_position_target_local_ned_encode(system_id, component_id, &msg, &sp); send_mavlink_message(&msg);
Example
This example shows how to control a PX4 drone in offboard mode using Python and the pymavlink library. It connects to the drone, switches to offboard mode, and sends position setpoints to hover at 5 meters altitude.
python
from pymavlink import mavutil import time # Connect to the drone master = mavutil.mavlink_connection('udp:127.0.0.1:14540') master.wait_heartbeat() print('Heartbeat from system (system %u component %u)' % (master.target_system, master.target_component)) # Function to send position setpoint def send_position_setpoint(x, y, z): master.mav.set_position_target_local_ned_send( int(time.time() * 1000), master.target_system, master.target_component, mavutil.mavlink.MAV_FRAME_LOCAL_NED, 0b0000111111000111, # ignore velocity, acceleration, yaw x, y, z, # position 0, 0, 0, # velocity 0, 0, 0, # acceleration 0, 0) # yaw, yaw_rate # Set mode to OFFBOARD master.set_mode_offboard() # Arm the drone master.arducopter_arm() # Send setpoints at 10 Hz for 10 seconds start = time.time() while time.time() - start < 10: send_position_setpoint(0, 0, -5) # hover 5 meters above ground time.sleep(0.1) # Disarm after master.arducopter_disarm()
Output
Heartbeat from system (system 1 component 1)
Mode set to OFFBOARD
Armed
Sending position setpoints...
Disarmed
Common Pitfalls
- Not sending setpoints fast enough: PX4 requires continuous setpoints at ~10 Hz; otherwise, it exits offboard mode.
- Forgetting to arm the drone: Offboard mode requires the drone to be armed to move.
- Incorrect coordinate frames: Use the correct MAV_FRAME (usually LOCAL_NED) for position commands.
- Not switching to offboard mode: You must explicitly set the flight mode to offboard before sending commands.
c
/* Wrong: Sending one setpoint and stopping */ send_position_setpoint(0, 0, -5); // No further commands sent, drone will exit offboard mode /* Right: Continuously sending setpoints */ while (true) { send_position_setpoint(0, 0, -5); sleep(100); // 10 Hz }
Quick Reference
- Enable offboard mode: Set flight mode to OFFBOARD.
- Arm drone: Arm before sending commands.
- Send setpoints: Use
SET_POSITION_TARGET_LOCAL_NEDor similar MAVLink messages. - Maintain rate: Send commands at 10 Hz or faster.
- Coordinate frame: Use LOCAL_NED for position control.
Key Takeaways
Enable offboard mode and arm the drone before sending commands.
Continuously send position or velocity setpoints at 10 Hz to maintain control.
Use the correct MAVLink messages and coordinate frames (usually LOCAL_NED).
Failing to send setpoints regularly causes PX4 to exit offboard mode.
Test commands in simulation before flying a real drone for safety.