Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
765e737
make files pass the linter
kaiden-keane Feb 14, 2026
0eaa055
remove debug_analysis, most of what it did can be done in debug.py an…
kaiden-keane Feb 15, 2026
cf9e5c4
fix type errors in imaging
kaiden-keane Feb 15, 2026
7edd440
rename files that are not true pytest tests to not have test in it so…
kaiden-keane Feb 15, 2026
9a5d8a5
test_nn was not doing anything actually helpful with shephard and sho…
kaiden-keane Feb 15, 2026
a7a542b
remove labeller from path for testing -- not used anymore
kaiden-keane Feb 15, 2026
235d660
fix analysis test small errors
kaiden-keane Feb 15, 2026
87b1f14
fix lint stuff again
kaiden-keane Feb 15, 2026
2127db7
Updated mavctl submodule
HameedFawwaz Feb 21, 2026
e19140a
add aiohttp and depthai to requirements.txt
kaiden-keane Feb 21, 2026
53021d8
Fixed test_battery.py test failure
HameedFawwaz Feb 24, 2026
833867c
Merge branch 'cleaning' of github.com:uaarg/shepard into cleaning
HameedFawwaz Feb 24, 2026
d9911cc
updated mavctl dependency to latest version
HameedFawwaz Feb 24, 2026
3984981
updated mavctl submodule and updated fixed test with previous droneki…
HameedFawwaz Feb 24, 2026
8e7cfec
updated test.sh to properly init submodule before running
HameedFawwaz Feb 24, 2026
d404005
fied test/test_camera.py
HameedFawwaz Feb 24, 2026
5c895ac
downgrade depthai to 2.0 in requirements.txt
kaiden-keane Mar 7, 2026
13dd1d9
fix bad imports
kaiden-keane Mar 7, 2026
13ff23b
fix some type errors on initializing queue
kaiden-keane Mar 7, 2026
0855c2b
Merge branch 'main' into cleaning
kaiden-keane Mar 20, 2026
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
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ typing_extensions==4.9.0
yapf==0.40.1
zipp==3.17.0
ultralytics==8.3.128
websockets==15.0.1
aiohttp==3.13.3
depthai==2.32.0
23 changes: 0 additions & 23 deletions samples/bucket_test.py

This file was deleted.

47 changes: 0 additions & 47 deletions samples/bucket_test_simple.py

This file was deleted.

27 changes: 7 additions & 20 deletions samples/emu_connection.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,20 @@
from src.modules.emu import Emu
from src.modules.emu.emu import Emu
import time
import json

emu = Emu("res")

# def onConnect():
# loadCurrent = {
# "type": "load",
# "uavStatus": {
# "connection": "no",
# "mode": "test",
# "imageCount": "2",
# "timeSinceMessage": "3"
# },
# "imageName": "res/sample1.jpg"
# }
# emu.send_msg(json.dumps(loadCurrent))


# emu.set_on_connect(onConnect)
emu.start_comms()
time.sleep(2)

# test different logs
for i in range(6):
print(f"sending log {i}")
if i % 3 == 0: severity = "normal"
elif i % 3 == 1: severity = "warning"
else: severity = "error"
if i % 3 == 0:
severity = "normal"
elif i % 3 == 1:
severity = "warning"
else:
severity = "error"
emu.send_log(f"log text {i}", severity)
time.sleep(1)

Expand Down
2 changes: 0 additions & 2 deletions samples/geofence_test.py → samples/geofence.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,3 @@
print(lander.geofence_check(point5))
print(lander.geofence_check(point6))
print(lander.geofence_check(point7))


1 change: 0 additions & 1 deletion samples/img_test.py → samples/img_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ def test(img, _):
print("Image taken")



analysis = ImageAnalysisDelegate(detector, camera, location)
analysis.subscribe(test)

Expand Down
21 changes: 0 additions & 21 deletions samples/kml_mock.py

This file was deleted.

8 changes: 6 additions & 2 deletions samples/oakd.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from PIL import Image
from src.modules.emu import Emu
from src.modules.emu.emu import Emu
import time
import json
import threading
Expand All @@ -9,9 +9,11 @@
emu = Emu("tmp")
i = 0


def print_conn():
print("connecton made")


emu.set_on_connect(print_conn)
latest_capture: DepthCapture | None = None

Expand All @@ -23,6 +25,7 @@ def print_conn():
camera_thread = threading.Thread(target=camera.start(), daemon=True)
camera_thread.start()


def send_img(message):
global latest_capture, i

Expand All @@ -38,6 +41,7 @@ def send_img(message):

i += 1


def measure(message):
global latest_capture

Expand All @@ -53,7 +57,7 @@ def measure(message):
if latest_capture is not None:
distance = latest_capture.distance_between_points(p1["x"], p1["y"], p2["x"], p2["y"])
send = {
"type": "distance",
"type": "distance",
"message": distance
}
emu.send_msg(json.dumps(send))
Expand Down
53 changes: 0 additions & 53 deletions samples/test_nn.py

This file was deleted.

4 changes: 3 additions & 1 deletion scripts/test.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#!/usr/bin/env sh

PYTHONPATH=".:dep/labeller" pytest
pip install -e src/modules/mavctl

PYTHONPATH="." pytest
1 change: 0 additions & 1 deletion src/modules/emu/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
from .emu import *
7 changes: 3 additions & 4 deletions src/modules/emu/emu.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def send_image(self, path: str):
}
self._send_queue.put(json.dumps(content))

def send_log(self, message: str, severity: str="normal"):
def send_log(self, message: str, severity: str = "normal"):
"""
sends a log message to Emu
message: string of flog
Expand Down Expand Up @@ -87,7 +87,6 @@ async def producer_handler(self, ws):
"""
handles sending messages to the client
"""
event_loop = asyncio.get_running_loop()
while not ws.closed:
message = await asyncio.to_thread(self._send_queue.get)

Expand All @@ -101,7 +100,7 @@ async def consumer_handler(self, ws):

elif msg.type == aiohttp.WSMsgType.ERROR:
print("WebSocket error:", ws.exception())

async def handle_websocket(self, request):
ws = web.WebSocketResponse()
await ws.prepare(request)
Expand All @@ -122,5 +121,5 @@ async def handle_websocket(self, request):

print('websocket connection closed')
self._is_connected = False

return ws
38 changes: 20 additions & 18 deletions src/modules/imaging/analysis.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Callable, Optional, List, Callable, Any
from typing import Callable, List, Callable, Any

import threading
# from multiprocessing import Process
Expand All @@ -7,7 +7,8 @@
from .debug import ImageAnalysisDebugger
from ..georeference.inference_georeference import get_object_location
from .location import LocationProvider
from ..autopilot.navigator import Navigator
#from ..autopilot.navigator import Navigator
from mavctl.messages.navigator import Navigator
from PIL import Image


Expand Down Expand Up @@ -46,9 +47,9 @@ class ImageAnalysisDelegate:
def __init__(self,
detector: BaseDetector,
camera: CameraProvider,
location_provider: LocationProvider = None,
navigation_provider: Navigator = None,
debugger: Optional[ImageAnalysisDebugger] = None):
location_provider: LocationProvider | None = None,
debugger: ImageAnalysisDebugger | None = None,
navigation_provider: Navigator | None = None):
self.detector = detector
self.camera = camera
self.debugger = debugger
Expand All @@ -59,22 +60,30 @@ def __init__(self,
self.location_provider = location_provider
self.navigation_provider = navigation_provider

self.subscribers: List[Callable[[Image.Image, float, float], Any]] = []
self.subscribers: List[Callable[[Image.Image, tuple[float, float] | None], Any]] = []
self.camera_attributes = CameraAttributes()
self.thread = None

self.loop = True

def get_inference(self, bounding_box: BoundingBox) -> Inference:
if self.location_provider is not None:
altitude = self.location_provider.altitude()
elif self.navigation_provider is not None:
altitude = -1 * self.navigation_provider.get_local_position_ned()[2]
altitude = -1 * self.navigation_provider.get_local_position().down
else:
raise ValueError("No altitude information provider available.")

inference = Inference(bounding_box, altitude)
return inference

def _analysis_loop(self):
"""
Indefinitely run image analysis. This should be run in another thread;
use `start()` to do so.
"""
while self.loop:
self._analyze_image()

def start(self):
"""
Will start the image analysis process in another thread.
Expand All @@ -87,8 +96,9 @@ def start(self):
# Use `threading` to start `self._analysis_loop` in another thread.

def stop(self):
self.loop = False
self.thread.join()
if self.thread is not None:
self.loop = False
self.thread.join()

def _analyze_image(self):
"""
Expand All @@ -114,14 +124,6 @@ def _analyze_image(self):
else:
subscriber(im, None)

def _analysis_loop(self):
"""
Indefinitely run image analysis. This should be run in another thread;
use `start()` to do so.
"""
while self.loop:
self._analyze_image()

def subscribe(self, callback: Callable):
"""
Subscribe to image analysis updates. For example:
Expand Down
2 changes: 1 addition & 1 deletion src/modules/imaging/bucket_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from PIL import Image

from .detector import Vec2, BoundingBox, BaseDetector
from .detector import Vec2, BoundingBox, BaseDetector

from ultralytics import YOLO

Expand Down
Loading
Loading