Hi everyone,
I’m trying to control a drone in offboard attitude mode using ROS2 + PX4 (SITL Gazebo, X500 model).
What works
-
Offboard mode is correctly engaged
-
Vehicle arms successfully
-
Motors spin
-
Attitude setpoints are published at 50 Hz
Problem
The drone never takes off, no matter the thrust value (tested from 0.5 up to 1.0).
Code
import rclpy
from rclpy.node import Node
import numpy as np
from px4_msgs.msg import OffboardControlMode
from px4_msgs.msg import VehicleAttitudeSetpoint
from px4_msgs.msg import VehicleCommand
class AttitudeTakeoff(Node):
def __init__(self):
super().__init__('attitude_takeoff_node')
self.offboard_pub = self.create_publisher(
OffboardControlMode,
'/fmu/in/offboard_control_mode',
10)
self.attitude_pub = self.create_publisher(
VehicleAttitudeSetpoint,
'/fmu/in/vehicle_attitude_setpoint',
10)
self.cmd_pub = self.create_publisher(
VehicleCommand,
'/fmu/in/vehicle_command',
10)
self.timer = self.create_timer(0.02, self.timer_callback)
self.counter = 0
def arm(self):
msg = VehicleCommand()
msg.command = VehicleCommand.VEHICLE_CMD_COMPONENT_ARM_DISARM
msg.param1 = 1.0
msg.target_system = 1
msg.target_component = 1
msg.from_external = True
self.cmd_pub.publish(msg)
def set_offboard_mode(self):
msg = VehicleCommand()
msg.command = VehicleCommand.VEHICLE_CMD_DO_SET_MODE
msg.param1 = 1.0
msg.param2 = 6.0 # OFFBOARD
msg.target_system = 1
msg.target_component = 1
msg.from_external = True
self.cmd_pub.publish(msg)
def level_quaternion(self):
return [1.0, 0.0, 0.0, 0.0]
def timer_callback(self):
offboard_msg = OffboardControlMode()
offboard_msg.attitude = True
offboard_msg.body_rate = False
offboard_msg.position = False
offboard_msg.velocity = False
offboard_msg.timestamp = int(self.get_clock().now().nanoseconds / 1000)
self.offboard_pub.publish(offboard_msg)
attitude_msg = VehicleAttitudeSetpoint()
attitude_msg.q_d = self.level_quaternion()
thrust = -1.0
attitude_msg.thrust_body = [0.0, 0.0, thrust]
attitude_msg.timestamp = offboard_msg.timestamp
self.attitude_pub.publish(attitude_msg)
if self.counter == 50:
self.set_offboard_mode()
self.arm()
self.counter += 1
def main(args=None):
rclpy.init(args=args)
node = AttitudeTakeoff()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
Questions
-
Is it actually possible to take off using only
VehicleAttitudeSetpointin PX4 offboard mode? -
Could internal PX4 controllers still override or limit thrust in this mode?
-
Is there any takeoff protection preventing lift-off in attitude mode?
-
Does the X500 model require specific parameters or thrust scaling?
Thanks a lot for your help