Instance-segmentation model for the "hang the wire" hook mission of the SAE
Brasil Eletroquad 2026 competition, trained by
Black Bee Drones. It segments two
classes -
rose (each visible segment of the suspended rope) and
sphere
(the orange sphere on the rope) - and runs on every control-loop tick of the
mission. The team finished 2nd overall
(
official results).
The drone takes off, finds the orange sphere mounted on one of two suspended
ropes, parks a fixed distance from it, picks which side of the rope to fly
along, turns perpendicular to the rope, descends on LIDAR, releases a hook with
a servo, and lands. Because each visible rope segment is its own
rose
instance, the controller can measure both rope arms and choose a side. The
mission runs on a Jetson Orin Nano through
Nectar SDK.
Evaluated on the dataset's
test split (395 images, 501 instances), NMS
iou=0.6. The numbers below are Ultralytics-native (COCO 101-point
interpolation); see
SUMMARY.md for the full breakdown, including
the SDK/torchmetrics figures (which run a different curve discretization and
read systematically lower at mAP@50-95).
Operating-point precision / recall / F1 at the per-class optimal confidences
(from the F1 curve):
Predict at the lower of the two confidences and apply a per-class filter, so
each class keeps its own threshold.
1from nectar.ai.segmentation import Segmentor
2from nectar.ai.detection.postprocess import PerClassConfidenceFilter
3
4# loads weights/best.pt from the Hub
5segmentor = Segmentor("blackbeedrones/sae-2026-hang-all-yolo26n-seg-v2-960")
6segmentor.load()
7
8result = segmentor.segment(image, conf=0.47, iou=0.6, imgsz=960)
9
10# rose=0, sphere=1
11per_class = PerClassConfidenceFilter(threshold_mapping={0: 0.47, 1: 0.70}, default_threshold=0.47)
12kept = per_class.filter(result.to_supervision())
13for seg in result:
14 print(seg.class_name, f"{seg.confidence:.2f}", f"area={seg.mask_area}px")
1from huggingface_hub import hf_hub_download
2from ultralytics import YOLO
3
4weights = hf_hub_download("blackbeedrones/sae-2026-hang-all-yolo26n-seg-v2-960", "weights/best.pt")
5model = YOLO(weights)
6results = model.predict("image.jpg", imgsz=960, iou=0.6, conf=0.47)
Trained with Ultralytics through the Nectar SDK on
blackbeedrones/sae-2026-hook
(Roboflow
sae-2026-hang v2: 9,235 train / 396 val / 395 test images). Full
configuration in
experiment.config.yaml.