feat: Remove ROS2 dependency, enhance arming with retries, and improve takeoff sequence with better altitude monitoring and arming failure handling.

This commit is contained in:
2026-01-07 20:29:11 +00:00
parent 1eb0d23fb9
commit 760293d896

View File

@@ -31,14 +31,6 @@ except ImportError:
print("Run: pip install pymavlink") print("Run: pip install pymavlink")
sys.exit(1) sys.exit(1)
try:
import rclpy
from rclpy.node import Node
ROS2_AVAILABLE = True
except ImportError:
ROS2_AVAILABLE = False
print("[WARN] ROS 2 (rclpy) not available - using standalone controller")
from config import ARDUPILOT, CONTROLLER, MAVLINK from config import ARDUPILOT, CONTROLLER, MAVLINK
@@ -83,10 +75,11 @@ class ArduPilotInterface:
if msg_type == "HEARTBEAT": if msg_type == "HEARTBEAT":
self.armed = (msg.base_mode & mavutil.mavlink.MAV_MODE_FLAG_SAFETY_ARMED) != 0 self.armed = (msg.base_mode & mavutil.mavlink.MAV_MODE_FLAG_SAFETY_ARMED) != 0
# Get mode name # Get mode name using mavutil helper
if hasattr(mavutil.mavlink, 'enums'): try:
mode_map = mavutil.mavlink.enums.get('COPTER_MODE', {}) self.mode = mavutil.mode_string_v10(msg)
self.mode = mode_map.get(msg.custom_mode, {}).get('name', str(msg.custom_mode)) except Exception:
self.mode = str(msg.custom_mode)
elif msg_type == "LOCAL_POSITION_NED": elif msg_type == "LOCAL_POSITION_NED":
self.position = {"x": msg.x, "y": msg.y, "z": msg.z} self.position = {"x": msg.x, "y": msg.y, "z": msg.z}
@@ -135,22 +128,32 @@ class ArduPilotInterface:
def arm(self, force=True): def arm(self, force=True):
"""Arm motors.""" """Arm motors."""
if force: print("[INFO] Arming...")
# Force arm (bypass checks)
self.mav.mav.command_long_send(
self.mav.target_system,
self.mav.target_component,
mavutil.mavlink.MAV_CMD_COMPONENT_ARM_DISARM,
0, 1, 21196, 0, 0, 0, 0, 0 # 21196 = force arm
)
else:
self.mav.arducopter_arm()
time.sleep(1) for attempt in range(3):
self.update_telemetry() if force:
if self.armed: # Force arm (bypass checks)
print("[OK] Armed") self.mav.mav.command_long_send(
return self.armed self.mav.target_system,
self.mav.target_component,
mavutil.mavlink.MAV_CMD_COMPONENT_ARM_DISARM,
0, 1, 21196, 0, 0, 0, 0, 0 # 21196 = force arm
)
else:
self.mav.arducopter_arm()
# Wait and check if armed
time.sleep(1)
self.update_telemetry()
if self.armed:
print("[OK] Armed")
return True
else:
print(f"[WARN] Arm attempt {attempt + 1}/3 failed, retrying...")
print("[ERROR] Failed to arm after 3 attempts")
return False
def disarm(self): def disarm(self):
"""Disarm motors.""" """Disarm motors."""
@@ -279,22 +282,30 @@ def main():
# Set GUIDED mode and arm # Set GUIDED mode and arm
print("[INFO] Setting up for takeoff...") print("[INFO] Setting up for takeoff...")
ardupilot.set_mode("GUIDED") ardupilot.set_mode("GUIDED")
time.sleep(1) time.sleep(2) # Give mode time to change
ardupilot.arm(force=True) # Update telemetry to get current mode
time.sleep(1) ardupilot.update_telemetry()
print(f"[INFO] Current mode: {ardupilot.mode}")
if ardupilot.armed: if not ardupilot.arm(force=True):
print("[ERROR] Could not arm - continuing in manual mode")
print("[INFO] Use MAVProxy to arm: arm throttle force")
else:
ardupilot.takeoff(args.takeoff_alt) ardupilot.takeoff(args.takeoff_alt)
print(f"[INFO] Taking off to {args.takeoff_alt}m...") print(f"[INFO] Taking off to {args.takeoff_alt}m...")
# Wait for takeoff # Wait for takeoff (up to 15 seconds)
for _ in range(50): # 5 seconds for i in range(150):
telemetry = ardupilot.get_telemetry() telemetry = ardupilot.get_telemetry()
if telemetry["altimeter"]["altitude"] > args.takeoff_alt * 0.9: alt = telemetry["altimeter"]["altitude"]
print("[OK] Reached target altitude") if alt > args.takeoff_alt * 0.9:
print(f"\n[OK] Reached target altitude ({alt:.1f}m)")
break break
if i % 10 == 0:
print(f"\r[INFO] Climbing... {alt:.1f}m / {args.takeoff_alt}m", end="")
time.sleep(0.1) time.sleep(0.1)
print("")
print("\n[INFO] Starting controller loop...") print("\n[INFO] Starting controller loop...")
print("[INFO] Press Ctrl+C to stop\n") print("[INFO] Press Ctrl+C to stop\n")