Copter SITL disarms immediately after ARM in GUIDED mode when using MAVROS local position setpoints (ROS2)

I’m facing a persistent issue with ArduPilot Copter SITL + MAVROS (ROS 2) where the vehicle arms successfully but disarms automatically within a second, even though I am continuously streaming valid setpoints.

Setup Details

  • Vehicle: ArduCopter SITL

  • ROS 2 distro:bHumble

  • MAVROS: ROS 2 version

  • Companion control: External offboard node (Python, rclpy)

  • Simulation: SITL (Gazebo not involved)

What I am trying to do

  • Fly in GUIDED mode

  • Control the vehicle using local position setpoints

  • Topic used: /mavros/setpoint_position/local (geometry_msgs/PoseStamped)

  • Position feedback confirmed on:/mavros/local_position/pose

Mission flow:

  1. Wait for valid local position

  2. Switch to GUIDED mode

  3. Stream position setpoints continuously (>20 Hz)

  4. Arm the vehicle

  5. Command takeoff to ~2 m altitude

Observed Problem

  • Vehicle switches to GUIDED

  • Vehicle arms successfully

  • Immediately after arming:

AP: Arming motors
ARMED
Arming checks disabled
AP: Disarming motors
DISARMED

  1. This happens consistently
  2. No RC input is involved

:white_check_mark: What I have verified

  • Setpoints are published continuously before and after arming

  • Publishing rate is stable (>20 Hz)

  • /mavros/local_position/pose is valid before arming

  • QoS for local position subscriber is set to BEST_EFFORT (to match MAVROS)

  • GUIDED mode is active before arming

  • Setpoints are in local frame, not global

  • No explicit mode change or disarm command is sent by my node

My Questions

  1. What internal ArduPilot conditions cause an automatic DISARM immediately after ARM in GUIDED mode?

  2. Is there a specific failsafe related to:

    • Position estimate validity?

    • GUIDED setpoint type?

    • EKF origin / local frame?

  3. Is it mandatory to:

    • Send a MAV_CMD_NAV_TAKEOFF command instead of only position setpoints?
  4. Are there parameters (e.g., FS_GCS_ENABLE, GUID_TIMEOUT, EKF checks) that typically trigger this behavior in SITL?

Thank you for your time.
I’m trying to understand the correct internal mechanism, not just apply trial-and-error fixes.

Arming checks should be passing.

But i think Arming checks are for pre-arm verification. do they affect post arm failsafe ?

Disabling them masks a lot of problems. For example here the copter immediately fail-safes and since it is landed it disarms.

What is DISARM_DELAY set to?

Doesn’t matter, if the copter believes it is on the ground it will disarm immediately on failsafe.

DISARM_DELAY is set to : 10

I didn’t find ARMING_CHECK param but got these:

ARMING_ACCTHRESH 0.75
ARMING_MAGTHRESH 100
ARMING_MIS_ITEMS 0
ARMING_NEED_LOC 0
ARMING_OPTIONS 0
ARMING_RUDDER 2
ARMING_SKIPCHK 0

It got replaced with this one, now fix prearm issues and possibly arming issues and it should work. You may need to send takeoff command but that it is easy to check on your side.

I tried using ROS by first sending the takeoff command and then starting setpoint publishing, and this works correctly.

However, when I try to control the vehicle using only setpoint (position) or velocity commands, without sending an explicit takeoff command first, it does not work and eventually triggers a failsafe.

Why does the vehicle behave correctly when a takeoff command is used first, but not when using only pure setpoint or velocity commands?

I guess it doesn’t automatically transition from landed to flying for safety, you don’t want the vehicle to unexpectedly take off, or worse, try to slide along the ground.

That make sense Ok then I will go with that approach, thank you.