Skip to content
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions modules/mavlink/flight_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,23 @@ def get_odometry(self) -> "tuple[bool, drone_odometry_global.DroneOdometryGlobal

return True, odometry_data

def get_location(self) -> "tuple[bool, tuple[float, float, float] | None]":
"""Return (lat, lon, alt) if available via the drone, otherwise (False, None)."""
try:
loc = self.drone.location
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depending on how your test goes, you might have to replace this with receiving the "GLOBAL_POSITION_INT" mavlink message

except Exception: # pylint: disable=broad-except
print("HITL get_location error")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generalize this error message (ie. say something like "Error with requesting location" or "get_location could not complete request"). flight_controller is used on our general airside system

return False, None

if loc is None or loc.global_frame is None:
return False, None

gf = loc.global_frame
if gf.lat is None or gf.lon is None or gf.alt is None:
return False, None

return True, (gf.lat, gf.lon, gf.alt)

def get_home_position(
self, timeout: float
) -> "tuple[bool, position_global.PositionGlobal | None]":
Expand Down
129 changes: 129 additions & 0 deletions tests/integration/hitl/test_hitl_emulator_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
"""
HITL Test - GPS + Camera Feed Verification

"""

import cv2
import os
import time

from modules.mavlink import flight_controller


# Physical connection to Pixhawk: /dev/ttyAMA0
# Simulated connection to Pixhawk: tcp:localhost:5762
PIXHAWK_ADDRESS = "/dev/ttyAMA0"
TEST_DURATION = 10


def test_camera_feed() -> bool:
"""
Returns True if camera feed is available, False otherwise.
"""
try:
camera = cv2.VideoCapture(2)

if not camera.isOpened():
camera.release()
return False

ret, frame = camera.read()
camera.release()

if ret and frame is not None and frame.size > 0:
return True

return False

except Exception:
return False


def main() -> int:
"""
GPS data reading + camera feed check.
Returns 0 on success, non-zero on failure.
"""
images_path = os.path.join("tests", "integration", "camera_emulator", "images")

print("HITL Test")
print("=============")

# Create FlightController with HITL enabled
result, controller = flight_controller.FlightController.create(
PIXHAWK_ADDRESS, 57600, True, True, True, images_path
)

if not result or controller is None:
print("ERROR: FlightController creation failed")
return -1

print("FlightController created")

# Start HITL emulators
if controller.hitl_instance is not None:
controller.hitl_instance.start()
print("HITL emulators started")

print("Waiting for camera creation...")
time.sleep(5)

print("Checking for camera...")
camera_available = test_camera_feed()
if camera_available:
print("Camera: detected")
else:
print("Camera: not detected")

else:
print("ERROR: HITL instance not created")
return -1

try:
print(f"\nRunning test for {TEST_DURATION}s...")
start_time = time.time()
gps_count = 0
camera_count = 0

while time.time() - start_time < TEST_DURATION:
current_time = time.time() - start_time

# Test GPS data every 2 seconds
if int(current_time) % 2 == 0 and current_time > 0:
success, location = controller.get_location()
if success and location is not None:
lat, lon, alt = location
gps_count += 1
print(f"GPS: {lat:.6f}, {lon:.6f}, {alt:.1f}m")
else:
print("GPS: No data")

# Test camera feed every 3 seconds
if int(current_time) % 3 == 0 and current_time > 1:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The camera test should be assuming no access to the emulators, try creating a video stream using cv2 and checking if it's receiving video.

if test_camera_feed():
camera_count += 1
print("Camera: Feed available")
else:
print("Camera: No feed")

time.sleep(0.5)

# Results
print(f"\nResults:")
print(f"GPS readings: {gps_count}")
print(f"Camera frames: {camera_count}")

success = gps_count > 0 and camera_count > 0
print("PASS" if success else "FAIL")
return 0 if success else 1

except Exception as exc:
print(f"Test error: {exc}")
return 1
finally:
if controller.hitl_instance is not None:
controller.hitl_instance.shutdown()


if __name__ == "__main__":
exit(main())