Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/PX4/PX4-Autopilot/llms.txt

Use this file to discover all available pages before exploring further.

Offboard mode lets an external system — a companion computer, ROS 2 node, or MAVSDK application — take control of the vehicle by streaming setpoints to PX4 in real time. Instead of a pilot moving sticks, your software sends position, velocity, acceleration, attitude, body rate, or direct thrust commands over MAVLink or a ROS 2 topic. PX4 executes them through its normal control pipeline while continuously verifying that the external controller is alive. Offboard mode is designed for research, custom autonomy, and advanced automation scenarios where the predefined waypoint system of Mission mode is too rigid. It is the foundation for behaviors like dynamic trajectory following, formation flight, visual servoing, and model-predictive control. The tradeoff is that safety responsibility shifts significantly to you as the developer.
Offboard control with ROS 2 requires significant care. PX4 cannot distinguish ROS 2 messages from an external controller from messages published by internal PX4 modules. Sending setpoint messages in any flight mode other than Offboard — or writing to topics that PX4 has not disabled — can cause collisions in the control pipeline and unpredictable, potentially catastrophic behavior. Read this page fully before implementing an offboard controller.

What Offboard mode does

When Offboard mode is active, PX4 hands authority over the specified control axes to the external controller. The OffboardControlMode message (ROS 2) or the type mask in a MAVLink setpoint message tells PX4 which internal control modules to disable so the external controller can write to them safely. PX4 still handles low-level motor mixing, ESC communication, sensor fusion, and failsafe logic. Your controller operates at a higher level, injecting setpoints into PX4’s control loops rather than driving hardware directly (unless you choose direct actuator control, which bypasses everything).

Heartbeat requirement

PX4 requires a continuous proof-of-life signal from the external controller at 2 Hz minimum. This signal tells PX4 that the external system is healthy and responsive.
  • MAVLink: The setpoint messages themselves serve as the heartbeat. If setpoints stop arriving, PX4 starts a timer and triggers the offboard loss failsafe after COM_OF_LOSS_T seconds.
  • ROS 2: The OffboardControlMode topic serves as the heartbeat. Stream it at 2 Hz or faster at all times. The TrajectorySetpoint (and other setpoint topics) only need to be published when the setpoint value changes — but OffboardControlMode must be continuous.
PX4 will not switch into Offboard mode on the first message. The external controller must stream the heartbeat for at least one second before PX4 will accept a mode switch to Offboard. This prevents accidental activation during system startup.
The 2 Hz minimum is a floor, not a recommendation. In practice, stream your heartbeat and setpoints at 10–50 Hz for smooth control response. Irregular timing at the minimum rate will cause visible jitter in vehicle motion.

Setpoint types

The setpoint type determines which PX4 control loops remain active and which estimates (position, velocity, attitude) are required.

ROS 2 setpoints

Set the OffboardControlMode field flags to enable the appropriate control level. Fields are prioritized from top to bottom — the first non-zero field determines the active control mode.
Control levelOffboardControlMode flagRequired messageRequired estimate
Position (NED)position = trueTrajectorySetpointPosition (GPS/VIO)
Velocity (NED)velocity = trueTrajectorySetpointVelocity
Acceleration (NED)acceleration = trueTrajectorySetpointAttitude
Attitude (FRD)attitude = trueVehicleAttitudeSetpointAttitude
Body rate (FRD)body_rate = trueVehicleRatesSetpointAngular velocity
Thrust + torquethrust_and_torque = trueVehicleThrustSetpoint + VehicleTorqueSetpointNone
Direct actuatorsdirect_actuator = trueActuatorMotors + ActuatorServosNone
For multicopters using TrajectorySetpoint, the actual active controller (position, velocity, or acceleration) depends on which fields in the message are non-NaN. Setting the velocity flag in OffboardControlMode but sending a non-NaN position value in TrajectorySetpoint will run the position controller — the OffboardControlMode flag alone does not override the setpoint content.
Use SET_POSITION_TARGET_LOCAL_NED with frame MAV_FRAME_LOCAL_NED or MAV_FRAME_BODY_NED:
  • Position setpoint: set x, y, z
  • Velocity setpoint: set vx, vy, vz
  • Combined position + velocity: both non-zero; velocity is used as a feedforward term
Use SET_ATTITUDE_TARGET for attitude control:
  • Attitude quaternion (q) + thrust scalar
  • Body rates (body_roll_rate, body_pitch_rate, body_yaw_rate) + thrust scalar

ROS 2 offboard example pattern

The standard pattern for a ROS 2 offboard controller follows these steps:
1

Set up the ROS 2 publisher

Create publishers for OffboardControlMode and TrajectorySetpoint (or whichever setpoint topic matches your control level). Create a subscriber for VehicleStatus to monitor the current flight mode.
self.offboard_mode_pub = self.create_publisher(
    OffboardControlMode, '/fmu/in/offboard_control_mode', 10)
self.trajectory_pub = self.create_publisher(
    TrajectorySetpoint, '/fmu/in/trajectory_setpoint', 10)
self.vehicle_status_sub = self.create_subscription(
    VehicleStatus, '/fmu/out/vehicle_status',
    self.vehicle_status_callback, 10)
2

Stream the heartbeat before requesting Offboard mode

Start a timer at 10 Hz and publish OffboardControlMode on every tick. Publish your initial setpoint (typically the vehicle’s current position to avoid sudden jumps). Wait for at least 1 second (10 ticks) before sending the mode switch command.
def publish_heartbeat(self):
    msg = OffboardControlMode()
    msg.position = True
    msg.velocity = False
    msg.acceleration = False
    msg.timestamp = self.get_clock().now().nanoseconds // 1000
    self.offboard_mode_pub.publish(msg)
3

Arm and switch to Offboard mode

Send VehicleCommand messages to arm the vehicle and switch to Offboard mode. Only do this after the heartbeat has been streaming for at least 1 second.
self.publish_vehicle_command(VehicleCommand.VEHICLE_CMD_DO_SET_MODE, 1.0, 6.0)
self.arm()
4

Publish setpoints at your control rate

Continue streaming OffboardControlMode as the heartbeat. Publish TrajectorySetpoint whenever you want the vehicle to move. Use NED coordinates (North-East-Down frame — positive Z is downward).
def publish_setpoint(self, x, y, z, yaw):
    msg = TrajectorySetpoint()
    msg.position = [x, y, z]   # NED frame; z is negative for altitude above home
    msg.yaw = yaw              # radians
    msg.timestamp = self.get_clock().now().nanoseconds // 1000
    self.trajectory_pub.publish(msg)
5

Handle mode transitions gracefully

Monitor VehicleStatus.nav_state to detect if PX4 has exited Offboard mode (due to failsafe or RC override). Stop publishing setpoints or switch to a safe hold behavior when this happens.
In ROS 2, PX4 cannot tell the difference between your external controller’s messages and messages from internal PX4 modules. Publish setpoint messages only when Offboard mode is active. Publishing to setpoint topics in other flight modes risks overwriting internal controller outputs and causing a crash.

Enabling and configuring Offboard mode

Key parameters

ParameterDescriptionDefault
COM_OF_LOSS_TTime in seconds to wait after the offboard connection is lost before triggering the failsafe action1.0 s
COM_OBL_RC_ACTFailsafe action when offboard connection is lost: 0 = Position, 1 = Altitude, 2 = Manual, 3 = Return, 4 = Land0 (Position)
COM_RC_OVERRIDEWhether RC stick movement during Offboard mode switches to Position mode (not enabled for Offboard by default)Disabled for Offboard
COM_RC_STICK_OVStick deflection threshold (%) that triggers RC override when COM_RC_OVERRIDE is enabled30%
COM_RCL_EXCEPTModes in which RC loss is ignored; set bit 2 to ignore RC loss in Offboard mode0
COM_RC_IN_MODESet to 4 to disable manual RC control entirely and allow offboard-only operation0

Activating Offboard mode

You can switch to Offboard mode via:
  • RC transmitter switch configured to Offboard in QGroundControl Vehicle Setup → Flight Modes
  • MAVLink MAV_CMD_DO_SET_MODE command (mode 6)
  • ROS 2 VehicleCommand message with VEHICLE_CMD_DO_SET_MODE
PX4 will refuse the switch if the heartbeat has not been streaming for at least 1 second.

Safety considerations

The default 1-second timeout is aggressive. If your companion computer reboots, experiences a watchdog reset, or if your ROS 2 executor lags, the vehicle may switch to the failsafe action before you can recover. For development, consider setting COM_OF_LOSS_T to 5–10 seconds and COM_OBL_RC_ACT to Return or Land. Tighten the timeout once your system is reliable.
Keep an RC transmitter ready with a mode switch that can pull the vehicle into Position mode or Return mode. Even if COM_RC_OVERRIDE is not enabled for Offboard mode by default, you can still switch modes manually via the mode switch. Test this override before every offboard flight.
Large discontinuities in position setpoints cause sudden, violent vehicle motion. When starting offboard control, your first setpoint should be the vehicle’s current position. When ending offboard control, transition through Hold mode rather than cutting the setpoint stream abruptly.
PX4 uses NED (North-East-Down) coordinates internally. ROS 2 uses ENU (East-North-Up) by convention. The PX4 ROS 2 interface (px4_msgs) uses NED — do not apply a standard ROS ENU-to-NED transform if you are using the raw PX4 uORB topics. Review the PX4-ROS 2 frame convention documentation carefully.
The PX4 ROS 2 Interface Library provides a higher-level, safer API for offboard control. It handles the OffboardControlMode heartbeat, mode switching, and some of the frame convention complexity for you. For production use cases, it is strongly preferred over the raw setpoint topics.
For development and testing, run PX4 SITL (Software In The Loop) simulation with Gazebo before flying hardware. This lets you validate your offboard controller’s behavior, including failsafe handling and mode transitions, without risk to a physical vehicle.

Build docs developers (and LLMs) love