Should We Perform Pre-Arm Safety Checks Before Sending the Arm Command?

I’ve been working with the PX4 ROS 2 official offboard example : px4_ros_com/src/examples/offboard/offboard_control.cpp at 86e9aeb20e55a4673fa8a9f1c29ea06a6c5ad1af · PX4/px4_ros_com · GitHub and noticed something I’d like to ask about.

Current Implementation

The example sends the arm command directly without verifying conditions first:

void OffboardControl::arm() {
    publish_vehicle_command(VehicleCommand::VEHICLE_CMD_COMPONENT_ARM_DISARM, 1.0);
    RCLCPP_INFO(this->get_logger(), "Arm command send");
}

My Observation

Looking at PX4’s Commander.cpp:606-677, arming is blocked when:

  • Pre-flight checks haven’t passed
  • Calibration is in progress
  • Health checks fail

And from offboardCheck.cpp, offboard mode additionally requires:

  • Valid offboard control signal
  • Valid local position (for position control)

My Question

Should the ROS 2 offboard example demonstrate checking these conditions before arming?

For example:

bool can_arm_offboard() {
    if (vehicle_status_.calibration_enabled) {
        RCLCPP_ERROR(get_logger(), "Cannot arm: calibration in progress");
        return false;
    }
    if (!vehicle_status_.pre_flight_checks_pass) {
        RCLCPP_ERROR(get_logger(), "Cannot arm: pre-flight checks failed");
        return false;
    }
    if (failsafe_flags_.offboard_control_signal_lost) {
        RCLCPP_ERROR(get_logger(), "Cannot arm: offboard signal lost");
        return false;
    }
    return true;
}

void arm() {
    if (!can_arm_offboard()) return;
    publish_vehicle_command(VehicleCommand::VEHICLE_CMD_COMPONENT_ARM_DISARM, 1.0);
}

Or is the current simplified approach mainly for tutorial purposes? For production ROS 2 applications with PX4, is it recommended to simply send the arm command and rely on PX4’s internal arming checks, or should the application first check conditions such as pre_flight_checks_pass, Offboard readiness/signal status, and then we should send arm command to PX4?

References

Hi there

First, as far as I’m aware, Offboard mode is no longer actively supported or developed, so some of the existing examples may also be outdated or no longer maintained.

In general, if you think you have a good idea, I’d suggest opening a small PR and starting the discussion from there. That will probably get you more concrete feedback on the proposed change.

Back to your question: my main concern is whether your proposal actually changes any behavior, or whether it mainly makes the fact that these checks are being run more explicit for readability.

When the ARM command is sent, the pre-arm checks are run anyway, and a message very similar to the one you propose printing is already emitted. So in practice, this would essentially run the pre-arm checks twice, which does not seem particularly clean or desirable.

Unless I’m missing another effect of the proposed change, I’m not sure there is much benefit beyond making the control flow slightly more explicit

Thank you for the reply.

No, my concern is not about performing the pre-arm checks twice. My concern is that when we control the drone remotely, either through Offboard mode, MAVLink/MAVSDK, or another library, the ROS 2 application runs separately from PX4, so it may not always know the current state of the drone. For example, if the user sends an arm command, the ROS 2 application may assume that the drone has been armed just because it sent the command. The application might then proceed with another action, such as sending a takeoff command, even though the arm command may have been rejected by PX4. This can create an inconsistency between the state assumed by the ROS 2 application and the actual state of the drone. Therefore, my point is that these checks can be used to verify the current vehicle state before sending the arm command. Since PX4 publishes this state information through the vehicle status topic, the ROS 2 application can use these flags to confirm the current status of the drone rather than assuming that a successfully sent command means the state has actually change.

I would keep PX4 as the final authority for whether arming is allowed, rather than duplicating the complete arming logic in the ROS 2 application.

However, for a production Offboard system I think there is still value in checking readiness before sending the arm request mainly as application state management and diagnostics, not as a replacement for PX4’s own safety checks.

I would separate the two responsibilities:

  • PX4: authoritative health/arming decision.

  • ROS 2 application: verify that its own prerequisites are present before requesting the transition valid Offboard stream, expected estimator/navigation state for the selected control mode, no known blocking condition, etc.

The application should still assume that the arm request can be rejected. In particular, I would also process VehicleCommandAck rather than interpreting “command sent” as “vehicle armed”.

That gives a useful sequence for a production state machine:

Offboard stream established → application readiness check → request Offboard → verify result/state → request arm → process ACK → verify armed state

This also avoids a subtle problem with duplicating PX4’s full pre-arm logic externally: the companion implementation can become stale as PX4 health/arming checks evolve.

So I think the current example is reasonable as a minimal tutorial, while a production example could demonstrate readiness monitoring and command acknowledgement without trying to reimplement Commander on the ROS 2 side.

Fully agree with this!

Its bad programming practice with PX4 to just send commands and expect them to go through. For any command that can fail, should include a check and what to do if it fails.

Exactly that distinction is important.

Sending the command is only a request; the application should explicitly handle the result and subsequent vehicle state. For an Offboard state machine, that also makes failures much easier to diagnose instead of silently continuing after a rejected transition.

Thanks for confirming.

Thank you for your replies and guidance. I think it is actually more than just a diagnostic/debugging issue or state consistency. It may also lead to more serious issues. For example, if we send trajectory commands without checking whether we are in Offboard mode or not, it could potentially lead to undefined behavior or, in some scenarios, even a drone crash. These are just my thoughts, but I wanted to know if this reasoning is valid.

Yes, I think your concern is valid, particularly for a production Offboard application.

I would distinguish between a rejected or ignored trajectory command and a failure in the companion application’s state management.

PX4 has its own mode and safety mechanisms, so sending a trajectory setpoint while Offboard mode is inactive does not automatically imply undefined vehicle behaviour. However, the companion application must not assume that its requested transition has succeeded.

A robust implementation should:

  1. Establish the required Offboard control stream.

  2. Request the mode transition.

  3. Process VehicleCommandAck.

  4. Independently verify the actual navigation state.

  5. Enable the appropriate trajectory execution logic only after confirmation.

  6. Handle rejection, timeouts and unexpected mode transitions explicitly.

One additional consideration is that checking the mode only once is insufficient. The application should continuously monitor the vehicle state throughout trajectory execution.

From a safety and incident-analysis perspective, I would also record the command request, acknowledgement, actual state transition and subsequent setpoints with their timestamps.

This would help distinguish a command rejection, an unexpected mode transition and an application-level sequencing failure during post-flight reconstruction.