如何在DroneKit中创建自定义Vehicle子类实例?
Great question! This is a super common frustration when working with DroneKit and PX4—since the Vehicle class is meant to be spun up via connect() instead of direct instantiation, regular subclassing feels broken. The good news is you can use delegation with Python's __getattr__ magic method to avoid that tedious self.vehicle.function() boilerplate.
Here's a step-by-step solution:
1. Build a Wrapper Class (With Delegation)
Instead of trying to directly inherit from Vehicle, create a wrapper class that holds a native Vehicle instance internally. Then use __getattr__ to automatically forward any unrecognized method/attribute calls to the internal instance. This lets you call native Vehicle methods directly on your custom class, just like you would with a regular Vehicle object.
2. Override PX4-Incompatible Methods
Any methods from the native Vehicle that don't play nice with PX4 can be redefined directly in your wrapper class—these will take precedence over the forwarded methods.
3. Add Your Custom Methods
Tack on any PX4-specific functionality you need as regular class methods.
Full Code Example
from dronekit import connect, VehicleMode import time import pymavlink.mavutil as mavutil class PX4CustomVehicle: def __init__(self, connection_string, *args, **kwargs): # Initialize the native Vehicle instance via connect() self._vehicle = connect(connection_string, *args, **kwargs) # Optional: Set up custom state/properties here self.px4_custom_flag = False # Override a native method to work with PX4 def arm(self): # PX4 requires setting GUIDED mode before arming in most cases self._vehicle.mode = VehicleMode("GUIDED") self._vehicle.armed = True # Wait for arming confirmation (PX4-specific wait logic) while not self._vehicle.armed: print("Waiting for vehicle to arm...") time.sleep(0.5) print("Vehicle armed with PX4-specific workflow!") # Add a completely custom PX4-focused method def trigger_px4_custom_action(self, param_value): # Send a custom MAVLink command specific to PX4 msg = self._vehicle.message_factory.command_long_encode( 0, 0, # Target system, target component mavutil.mavlink.MAV_CMD_USER_1, # Custom PX4 command 0, # Confirmation param_value, 0, 0, 0, 0, 0, 0 # Command parameters ) self._vehicle.send_mavlink(msg) self._vehicle.flush() print(f"Sent custom PX4 action with param: {param_value}") # The magic: Forward all unrecognized calls to the native Vehicle def __getattr__(self, name): # When we access a method/attribute not defined in our class, # grab it from the internal Vehicle instance instead return getattr(self._vehicle, name)
How to Use It
# Initialize your custom vehicle just like you would with connect() my_vehicle = PX4CustomVehicle("udp:127.0.0.1:14550") # Call your overridden arm method (PX4-compatible) my_vehicle.arm() # Call native Vehicle methods directly—no self._vehicle needed! my_vehicle.simple_takeoff(10) print(f"Current groundspeed: {my_vehicle.groundspeed}") # Run your custom PX4 method my_vehicle.trigger_px4_custom_action(42) # Don't forget to close the connection when done my_vehicle.close()
Key Notes
- Precedence: Any method you define directly in
PX4CustomVehiclewill override the nativeVehiclemethod of the same name. Perfect for fixing PX4 incompatibilities. - Attribute Forwarding: This works for properties too—things like
my_vehicle.parameters["THR_MIN"]will be forwarded to the internalVehicleinstance automatically. - Edge Cases: If you need to override a property (not just a method), use Python's
@propertydecorator in your wrapper class to handle that explicitly.
内容的提问来源于stack exchange,提问作者Eugene Valetsky

