Friday, October 16, 2026

 Insider-Risk Management with DVSA (https://github.com/ravibeta/dvsa-api) platform: 

Insider risk concerns model behavior and outputs that could significantly affect the analytics stack DVSA provides for drone AI applications, as described in the eponymous article. This document applies that article’s recommended trust architecture to our system. 

Models act like powerful insiders: they have access, intent, and the ability to act. DVSA relies on them for tasks ranging from geospatial pipelines to feedback control loops in critical mission systems. Our earlier work proposed two safeguards. The first is a health signal that measures semantic drift as the cosine distance between rolling embedding centroids. The second is a tiered architecture in which Qdrant global search and LLM agent reasoning run in the cloud. We now extend our scope beyond the data and infrastructure to the models themselves: how they act, which tools they can call, and how they might be manipulated or abused. 

In DVSA, every model, agent, and tool is an insider whose capabilities could leak information, misroute queries, amplify bias, or be steered by hostile input. We test the agent layer against prompt-injection attacks that hide directives in video metadata, and we mitigate them with SQL schema allowlists and input sanitization. We also protect data with AES-256-GCM encryption and differential privacy. Three principles govern every potential insider action: least privilege, strong provenance, and continuous monitoring. 

Least privilege begins with tools. The agentic retrieval layer exposes eight specialized functions, from semantic frame search to heatmap generation, and each should be tightly scoped. An agent answering a parking-lot query, for instance, should search only the relevant account, mission, and time window rather than the entire corpus. In Azure AI Search, we add accountid and video-id as filterable fields and pass OData filters such as odata_filter = "accountid eq '008333'". As a result, queries reach only the vectors derived from the user’s own uploaded videos, even though the index is shared across users. These filters are mandatory. Every agent tool call must carry tenant and mission context, which the API enforces and a policy engine such as Open Policy Agent validates. A model should never see more data than the current question requires. 

Provenance and lineage form the second pillar. We already attach provenance atomically at ingest and maintain full lineage graphs that trace every transformation from raw frame to archived artifact. These graphs support compliance audits, targeted reprocessing after model upgrades, and complete erasure cascades. We can extend this lineage to model decisions. Azure already produces a trace for every agent run, recording the tools called, frames retrieved, filters applied, model versions used, and the content of the final answer. These traces become our insider-activity logs. We can mine them for anomalies, such as an agent suddenly querying beyond its usual geospatial bounds or calling tools in a sequence that resembles reconnaissance rather than analysis. We then feed them into the same observability stack that monitors ingestion, localization, and drift. The result is a new signal, “model behavior drift,” which measures how far today’s tool-calling patterns deviate from a baseline of legitimate use. 

Exfiltration and misuse map cleanly onto DVSA’s multi-tenant, high-value corpus, because aerial urban video is sensitive by default. Our GDPR section already addresses this through four measures: purpose limitation enforced at flight-plan registration, importance sampling for data minimization, cascading deletion across the provenance database, S3, and Qdrant vectors, and latitude-longitude-time frame search for data subject access requests. We can add exfiltration guards at the agent layer. These would detect queries that resemble bulk export, such as “give me all frames with cars in Redmond between 2023 and 2025,” cap result sizes and aggregation granularity, and require elevated approval or out-of-band justification for queries that exceed those caps. We must scan not only prompts and their metadata but also the model behavior that attempts to fulfill them. 

Model supply chain and configuration drift are another dimension. DVSA requires embeddings to carry model-version metadata and orthophotos to be refreshed quarterly, and we trigger re-embedding when measured drift crosses a threshold. Building on this, we can treat model binaries, configuration files, and tool registries as high-risk artifacts. Any change to CLIP, YOLO, Qdrant index parameters, or agent tool definitions should pass through signed, auditable change control. Our dvsa_ Prometheus namespace can expose configuration hashes and model-version distributions and raise an alert when an unexpected version reaches production. This is how we catch a compromised model or misconfigured tool before it behaves like a malicious insider. 

Segmentation and isolation ensure that no single insider sees everything. DVSA’s tiered edge-versus-cloud architecture already provides a degree of segmentation, with Qdrant global search and LLM agent reasoning confined to the cloud. We can strengthen it in two ways: edge agents see only their own mission’s embeddings and metadata, and cloud agents operate in per-tenant namespaces with strict cross-tenant barriers. For cross-mission analytics, we can introduce specialized “auditor” agents with narrower tools and stronger logging instead of letting general-purpose agents roam the corpus. In effect, we assign our models roles, such as mission analyst, fleet auditor, and compliance checker, and give each role its own toolset and data scope. 

Finally, observability should cover activities as well as metrics. Alongside existing metrics such as agent task-completion rate and cost per query, we can add agent intent classification and tool-use entropy. A lightweight classifier could label each agent run as normal analysis, exploratory browsing, or suspicious bulk access based on its tool sequence, filter breadth, and result size. Tracking tool-use entropy per agent would reveal sudden spikes in unusual tools or filters that may indicate insider-like exploration. 

Taken together, these measures meet the expectations for insider-risk management: treating models, agents, and tools as insiders; atomic provenance; semantic drift monitoring; tiered edge and cloud deployment; access control lists; encryption; differential privacy; and a rich observability stack. 

 

Reference:  Insider risk eponymous article: https://snscratchpad.com/posts/models-as-insider-risks/  

Wednesday, October 14, 2026

 Self-Designed flight paths for fleet of autonomous drones

Leap71’s Noyron engine program is an example of encoding engineering as executable logic. Noyron is described by Leap71 as a “Large Computational Engineering Model” that takes a specification—thrust level, propellants, operating regime, manufacturing constraints—and directly generates manufacturable hardware, including complex internal fuel channels and radically different architectures such as bell nozzles and aerospikes. It does this by embedding first principles physics, engineering rules, and additive manufacturing constraints into a coherent codebase that outputs geometry and predicted operating parameters, which are then validated and refined through physical testing. 

The key idea is that Noyron is not a generic AI model trained on images or text; it is a domain specific computational model whose “DNA” encodes physics informed logic and design rules. Leap71 explicitly describes different engines—pressure fed demonstrators, monolithic copper aerospikes, and meganewton class turbomachinery systems—as “phenotypes of the same computational DNA.” That means the same underlying model can generate multiple architectures by varying parameters and constraints, without re deriving the engineering from scratch. The model produces geometry along with predicted pressures, temperatures, and flow rates, which are compared against test data from hot fire campaigns. Those tests feed back into the model, tightening its representation of propellant behavior, transient startup conditions, and material limits. 

Noyron’s efficiency climb up path looks like this:

1. Encode the domain: formalize physics, constraints, and design rules as executable code rather than informal documents.

2. Generate candidate designs directly from specifications.

3. Predict performance using embedded physics and logic.

4. Manufacture and test selected designs.

5. Compare predictions to measurements and update the model’s internal representation.

6. Iterate, exploring new phenotypes while reusing the same computational DNA.

The curvaceous fuel channels and unusual internal geometries are not aesthetic flourishes; they are emergent results of a model that is free to search the design space under constraints of fluid dynamics, heat transfer, structural integrity, and additive manufacturability. Large format metal powder bed fusion systems make it possible to print these complex monolithic components, which in turn allows Noyron to consider geometries that would be impractical with traditional multi part assemblies. 

Translating that methodology to drone fleet trajectory planning in a 3D space, a computational model must encode the rules of motion, constraints, and objectives, and then generate trajectories that maximize throughput between sources and destinations. Instead of fuel channels inside a rocket engine, your “geometry” is the set of paths through a discretized 3D volume—your matrix of waypoints—subject to dynamics, collision avoidance, and resource limits.

The first step is to define the domain in the code. That means:

• Drone dynamics: equations of motion, maximum acceleration, velocity limits, turning radii, climb and descent rates, and energy consumption as a function of trajectory.

• Environmental constraints: no fly zones, obstacles, altitude bands, wind fields if relevant, and communication or sensing limitations.

• Fleet level constraints: minimum separation distances, scheduling windows, launch and landing capacities, and any shared resources such as charging pads or air corridors.

• Objective function: what “throughput” means in your context—number of deliveries per unit time, total payload moved, latency bounds, or a weighted combination.

In drone flight, physics informed, constraint aware optimization model over a graph or continuous state space. You can represent the 3D space as a grid of nodes (waypoints) with edges representing feasible transitions that respect kinematic limits. Each edge carries a cost: time, energy, risk, or congestion. The fleet problem then becomes a multi agent routing and scheduling problem on this graph.

To mimic Noyron’s generative design approach, you don’t hand draw paths; you let the model synthesize them. Classical tools here include:

• Graph search algorithms such as A* or D* for single agent shortest paths, extended to multi agent settings with conflict based search or reservation based planning.

• Mixed integer linear or nonlinear programming formulations for multi commodity flow, where each drone is a “commodity” moving through the network, and throughput is maximized subject to capacity and separation constraints.

• Model predictive control (MPC) for continuous trajectory refinement, where a controller repeatedly solves a constrained optimization problem over a short horizon, updating paths as conditions change.

Noyron’s test and refine cycle can have an equivalent with simulated annealing. You start with a baseline model of dynamics and constraints, generate trajectories, simulate them, and then compare predicted performance to actual data from flight logs. Deviations—unexpected delays, energy usage, congestion patterns—are used to update the model. Over time fleet motion simulations become more accurate and can explore more aggressive optimizations.

One way to structure this is:

1. Build a physics informed simulator for your drones and environment. This is your analogue to Noyron’s internal physics engine.

2. Define a parametric policy or planner that maps tasks and environmental states to trajectories. Parameters might include weights in the objective function, safety margins, or routing heuristics.

3. Use optimization or learning to tune those parameters against throughput metrics in simulation, subject to safety constraints.

4. Deploy selected policies in limited real world trials, collect telemetry, and compare against simulation predictions.

5. Update both the simulator (to better match reality) and the planner (to exploit improved understanding), then iterate.

You can incorporate machine learning, but it should be grounded in the physics and constraints you’ve encoded. For example, reinforcement learning can be used to discover routing policies that maximize throughput, but the action space and reward function must respect collision avoidance and dynamic limits. Physics informed neural networks or hybrid models can refine parts of your simulator, such as energy consumption under complex wind conditions, while the overall planner remains optimization based. Data tightens the parameters rather than replacing the rules.

Drones move in continuous space, and you can generate continuous trajectories using optimal control and then project them onto a waypoint graph for scheduling and deconfliction.

Throughput maximization in a fleet context also demands attention to temporal coupling. It is not enough to find optimal paths; you must coordinate departures, arrivals, and crossings so that the system flows smoothly. Techniques from air traffic management and multi robot systems are relevant here: time expanded graphs where nodes represent space time positions, reservation tables that block edges during certain intervals, and priority schemes that resolve conflicts. Your computational model should be able to generate entire schedules—who goes where and when—given a set of tasks and constraints and then adjust them online as conditions change.

The final piece, inspired by Leap71’s code first philosophy, is to keep the entire pipeline executable and inspectable. Noyron’s strength lies in the fact that its engineering knowledge is trans codified into code that directly produces geometry and operating predictions. For your drone fleet, aim for a similar property given a specification of tasks, constraints, and objectives, the system should automatically produce trajectories and schedules, along with predicted metrics such as total throughput, average latency, and safety margins. When reality diverges, you don’t tweak paths manually; you update the model and let it regenerate solutions.

In practice, that means building:

• A well documented core model of dynamics and constraints.

• A set of optimization and planning modules that consume this model and output trajectories.

• A data assimilation layer that ingests telemetry and updates parameters.

• A validation loop where predicted and observed performance is routinely compared.

Treat that feedback loop as a code for trajectories: one that continuously compresses iteration times, explores non intuitive path geometries, and systematically climbs the efficiency curve toward maximum throughput in a constrained 3D space, and you have a self-organized flight path. Unlike self-organized Maps or pure hill-climbing approaches, this takes up the entire design space with the constraints before running iterations.



Tuesday, October 13, 2026

 

#!/usr/bin/env python3

"""Estimate drone altitude gain from nadir RGB video with LingBot-Map.


The script fits a ground plane to LingBot-Map world points and measures the

camera-to-plane distance for every frame. Monocular reconstruction has an

unknown global scale, so metric output requires --initial-altitude-m (or a

separate metric registration step). This is an analytics example, not a flight-

control or safety-critical altitude source.


Run from any directory after cloning/installing LingBot-Map:


  python altitude_gain_lingbot.py \

      --lingbot-repo /opt/lingbot-map \

      --model-path /models/lingbot-map.pt \

      --video-path flight.mp4 \

      --initial-altitude-m 18.4 \

      --output-csv altitude.csv \

      --summary-json altitude_summary.json

"""


from __future__ import annotations


import argparse

import csv

import json

import math

import sys

from contextlib import nullcontext

from pathlib import Path

from types import SimpleNamespace


import cv2

import numpy as np

import torch



def effective_sample_fps(video_path: str, requested_fps: int, stride: int) -> float:

    cap = cv2.VideoCapture(video_path)

    source_fps = float(cap.get(cv2.CAP_PROP_FPS) or 30.0)

    cap.release()

    interval = max(1, round(source_fps / requested_fps))

    return source_fps / interval / max(1, stride)



def fit_ground_plane_ransac(

    points: np.ndarray,

    optical_axis: np.ndarray,

    camera_center: np.ndarray,

    threshold: float,

    iterations: int,

    max_tilt_deg: float,

    seed: int,

) -> tuple[np.ndarray, float, np.ndarray]:

    """Return oriented unit normal, offset, and inlier mask for n.x + d = 0."""

    if len(points) < 100:

        raise ValueError(f"Too few candidate ground points: {len(points)}")


    rng = np.random.default_rng(seed)

    cos_limit = math.cos(math.radians(max_tilt_deg))

    optical_axis = optical_axis / np.linalg.norm(optical_axis)

    best_mask = None

    best_count = -1

    best_median = np.inf


    for _ in range(iterations):

        p0, p1, p2 = points[rng.choice(len(points), 3, replace=False)]

        n = np.cross(p1 - p0, p2 - p0)

        norm = np.linalg.norm(n)

        if norm < 1e-9:

            continue

        n /= norm

        if abs(float(n @ optical_axis)) < cos_limit:

            continue

        d = -float(n @ p0)

        residuals = np.abs(points @ n + d)

        mask = residuals <= threshold

        count = int(mask.sum())

        med = float(np.median(residuals[mask])) if count else np.inf

        if count > best_count or (count == best_count and med < best_median):

            best_mask, best_count, best_median = mask, count, med


    if best_mask is None or best_count < 100:

        raise RuntimeError(

            "Ground-plane RANSAC failed. Check that the video is nadir-looking, "

            "lower --confidence-threshold, or increase --plane-threshold-ratio."

        )


    inliers = points[best_mask]

    centroid = inliers.mean(axis=0)

    _, _, vh = np.linalg.svd(inliers - centroid, full_matrices=False)

    n = vh[-1]

    n /= np.linalg.norm(n)

    d = -float(n @ centroid)


    # Orient the plane normal toward the camera side of the ground plane.

    if float(n @ camera_center + d) < 0:

        n, d = -n, -d


    residuals = np.abs(points @ n + d)

    refined_mask = residuals <= threshold

    return n, d, refined_mask



def moving_median(values: np.ndarray, window: int) -> np.ndarray:

    if window <= 1:

        return values.copy()

    window = window if window % 2 == 1 else window + 1

    radius = window // 2

    padded = np.pad(values, (radius, radius), mode="edge")

    return np.array(

        [np.median(padded[i : i + window]) for i in range(len(values))],

        dtype=np.float64,

    )



def collect_plane_points(

    world_points: np.ndarray,

    confidence: np.ndarray,

    frame_count: int,

    confidence_threshold: float,

    center_fraction: float,

    pixel_stride: int,

    max_points: int,

    seed: int,

) -> np.ndarray:

    samples = []

    for i in range(min(frame_count, world_points.shape[0])):

        pts = np.asarray(world_points[i])

        conf = np.asarray(confidence[i]).squeeze()

        if pts.ndim != 3 or pts.shape[-1] != 3:

            raise ValueError(f"Unexpected world_points[{i}] shape: {pts.shape}")

        h, w = pts.shape[:2]

        y_margin = int((1.0 - center_fraction) * h / 2.0)

        x_margin = int((1.0 - center_fraction) * w / 2.0)

        ys = slice(y_margin, max(y_margin + 1, h - y_margin), pixel_stride)

        xs = slice(x_margin, max(x_margin + 1, w - x_margin), pixel_stride)

        p = pts[ys, xs].reshape(-1, 3)

        c = conf[ys, xs].reshape(-1)

        valid = np.isfinite(p).all(axis=1) & np.isfinite(c) & (c >= confidence_threshold)

        samples.append(p[valid])


    points = np.concatenate(samples, axis=0) if samples else np.empty((0, 3))

    if len(points) > max_points:

        rng = np.random.default_rng(seed)

        points = points[rng.choice(len(points), max_points, replace=False)]

    return points.astype(np.float64, copy=False)



def build_model_args(args: argparse.Namespace) -> SimpleNamespace:

    return SimpleNamespace(

        mode=args.mode,

        model_path=args.model_path,

        image_size=args.image_size,

        patch_size=14,

        enable_3d_rope=True,

        max_frame_num=1024,

        kv_cache_sliding_window=args.kv_cache_sliding_window,

        num_scale_frames=args.num_scale_frames,

        use_sdpa=args.use_sdpa,

        camera_num_iterations=args.camera_num_iterations,

    )



def run_lingbot(args: argparse.Namespace):

    repo = Path(args.lingbot_repo).resolve()

    if not (repo / "demo.py").is_file():

        raise FileNotFoundError(f"LingBot-Map demo.py not found under {repo}")

    sys.path.insert(0, str(repo))

    from demo import load_images, load_model, postprocess


    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    if device.type != "cuda":

        raise RuntimeError("This example expects a CUDA GPU for LingBot-Map inference.")


    images, paths, _ = load_images(

        video_path=args.video_path,

        fps=args.fps,

        stride=args.stride,

        first_k=args.first_k,

        image_size=args.image_size,

        patch_size=14,

    )

    if images.shape[0] < max(3, args.num_scale_frames):

        raise ValueError("The sampled video contains too few frames for reconstruction.")


    model_args = build_model_args(args)

    model = load_model(model_args, device)

    dtype = torch.bfloat16 if torch.cuda.get_device_capability()[0] >= 8 else torch.float16

    if getattr(model, "aggregator", None) is not None:

        model.aggregator = model.aggregator.to(dtype=dtype)

    images = images.to(device)


    frame_count = int(images.shape[0])

    keyframe_interval = args.keyframe_interval

    if keyframe_interval is None:

        keyframe_interval = math.ceil(frame_count / 320) if args.mode == "streaming" and frame_count > 320 else 1


    output_device = torch.device("cpu") if args.offload_to_cpu else None

    with torch.no_grad(), torch.autocast(device_type="cuda", dtype=dtype):

        if args.mode == "streaming":

            predictions = model.inference_streaming(

                images,

                num_scale_frames=args.num_scale_frames,

                keyframe_interval=keyframe_interval,

                output_device=output_device,

            )

        else:

            predictions = model.inference_windowed(

                images,

                window_size=args.window_size,

                overlap_size=args.overlap_size,

                overlap_keyframes=args.overlap_keyframes,

                num_scale_frames=args.num_scale_frames,

                keyframe_interval=keyframe_interval,

                output_device=output_device,

            )


    if args.offload_to_cpu:

        images_for_post = predictions.get("images")

        if images_for_post is None:

            raise KeyError("LingBot-Map did not return images while CPU offload was enabled.")

    else:

        images_for_post = images

    predictions, _ = postprocess(predictions, images_for_post)

    return predictions, paths, keyframe_interval



def parse_args() -> argparse.Namespace:

    p = argparse.ArgumentParser(

        description="Estimate relative or metric drone altitude gain using LingBot-Map."

    )

    p.add_argument("--lingbot-repo", required=True, help="Path to cloned Robbyant/lingbot-map")

    p.add_argument("--model-path", required=True, help="Path to lingbot-map.pt")

    p.add_argument("--video-path", required=True, help="Nadir/top-down drone video")

    p.add_argument("--output-csv", default="altitude_gain.csv")

    p.add_argument("--summary-json", default="altitude_summary.json")

    p.add_argument(

        "--initial-altitude-m",

        type=float,

        default=None,

        help="Known camera height above the fitted ground plane at the baseline frames; enables metres",

    )

    p.add_argument("--fps", type=int, default=10, help="Requested video sampling rate")

    p.add_argument("--stride", type=int, default=1, help="Additional stride after FPS sampling")

    p.add_argument("--first-k", type=int, default=None)

    p.add_argument("--image-size", type=int, default=518)

    p.add_argument("--mode", choices=("streaming", "windowed"), default="streaming")

    p.add_argument("--num-scale-frames", type=int, default=8)

    p.add_argument("--keyframe-interval", type=int, default=None)

    p.add_argument("--kv-cache-sliding-window", type=int, default=64)

    p.add_argument("--window-size", type=int, default=128)

    p.add_argument("--overlap-size", type=int, default=16)

    p.add_argument("--overlap-keyframes", type=int, default=16)

    p.add_argument("--camera-num-iterations", type=int, default=4)

    p.add_argument("--use-sdpa", action="store_true", help="Use PyTorch SDPA instead of FlashInfer")

    p.add_argument(

        "--offload-to-cpu",

        action=argparse.BooleanOptionalAction,

        default=True,

        help="Offload predictions to CPU during inference",

    )

    p.add_argument("--plane-frames", type=int, default=8)

    p.add_argument("--baseline-frames", type=int, default=3)

    p.add_argument("--confidence-threshold", type=float, default=1.5)

    p.add_argument("--center-fraction", type=float, default=0.8)

    p.add_argument("--pixel-stride", type=int, default=4)

    p.add_argument("--max-plane-points", type=int, default=30000)

    p.add_argument(

        "--plane-threshold-ratio",

        type=float,

        default=0.01,

        help="RANSAC distance tolerance as a fraction of initial camera-to-point range",

    )

    p.add_argument("--ransac-iterations", type=int, default=750)

    p.add_argument("--max-plane-tilt-deg", type=float, default=45.0)

    p.add_argument("--smooth-window", type=int, default=5)

    p.add_argument("--seed", type=int, default=7)

    return p.parse_args()



def main() -> None:

    args = parse_args()

    predictions, paths, keyframe_interval = run_lingbot(args)


    required = {"extrinsic", "world_points", "world_points_conf"}

    missing = required.difference(predictions)

    if missing:

        raise KeyError(f"LingBot-Map output is missing: {sorted(missing)}")


    extrinsic = np.asarray(predictions["extrinsic"])

    world_points = np.asarray(predictions["world_points"])

    confidence = np.asarray(predictions["world_points_conf"])

    if extrinsic.ndim == 4 and extrinsic.shape[0] == 1:

        extrinsic = extrinsic[0]

    if world_points.ndim == 5 and world_points.shape[0] == 1:

        world_points = world_points[0]

    if confidence.ndim == 4 and confidence.shape[0] == 1:

        confidence = confidence[0]


    camera_centers = extrinsic[:, :3, 3].astype(np.float64)

    camera_forward = extrinsic[:, :3, 2].astype(np.float64)

    mean_forward = camera_forward[: min(args.plane_frames, len(camera_forward))].mean(axis=0)


    plane_points = collect_plane_points(

        world_points,

        confidence,

        args.plane_frames,

        args.confidence_threshold,

        args.center_fraction,

        args.pixel_stride,

        args.max_plane_points,

        args.seed,

    )

    initial_range = np.median(np.linalg.norm(plane_points - camera_centers[0], axis=1))

    threshold = max(1e-6, args.plane_threshold_ratio * float(initial_range))

    normal, offset, inliers = fit_ground_plane_ransac(

        plane_points,

        mean_forward,

        camera_centers[0],

        threshold,

        args.ransac_iterations,

        args.max_plane_tilt_deg,

        args.seed,

    )


    altitude_model = camera_centers @ normal + offset

    altitude_model = moving_median(altitude_model, args.smooth_window)

    baseline_n = min(max(1, args.baseline_frames), len(altitude_model))

    baseline_model = float(np.median(altitude_model[:baseline_n]))

    if baseline_model <= 0:

        raise RuntimeError("Estimated baseline camera-to-ground distance is non-positive.")


    if args.initial_altitude_m is not None:

        scale = args.initial_altitude_m / baseline_model

        altitude = altitude_model * scale

        baseline = float(np.median(altitude[:baseline_n]))

        unit = "m"

    else:

        scale = 1.0

        altitude = altitude_model

        baseline = baseline_model

        unit = "lingbot_scale_units"

    gain = altitude - baseline


    sample_fps = effective_sample_fps(args.video_path, args.fps, args.stride)

    timestamps = np.arange(len(altitude), dtype=np.float64) / sample_fps


    output_csv = Path(args.output_csv)

    output_csv.parent.mkdir(parents=True, exist_ok=True)

    with output_csv.open("w", newline="", encoding="utf-8") as f:

        writer = csv.writer(f)

        writer.writerow(

            ["frame_index", "timestamp_s", "source_frame", f"altitude_{unit}", f"gain_{unit}"]

        )

        for i, (ts, alt, delta) in enumerate(zip(timestamps, altitude, gain)):

            source = paths[i] if i < len(paths) else ""

            writer.writerow([i, f"{ts:.6f}", source, f"{alt:.9f}", f"{delta:.9f}"])


    plane_residuals = np.abs(plane_points @ normal + offset)

    summary = {

        "video": str(Path(args.video_path).resolve()),

        "frames_processed": int(len(altitude)),

        "effective_sample_fps": sample_fps,

        "mode": args.mode,

        "keyframe_interval": keyframe_interval,

        "unit": unit,

        "metric_scale": scale if args.initial_altitude_m is not None else None,

        "baseline_altitude": baseline,

        "final_altitude": float(altitude[-1]),

        "final_gain": float(gain[-1]),

        "maximum_gain": float(np.max(gain)),

        "minimum_gain": float(np.min(gain)),

        "ground_plane_normal_lingbot_world": normal.tolist(),

        "ground_plane_offset_lingbot_world": offset,

        "plane_candidate_points": int(len(plane_points)),

        "plane_inlier_ratio": float(np.mean(inliers)),

        "plane_median_absolute_residual_model_units": float(np.median(plane_residuals[inliers])),

        "notes": [

            "Metric altitude is scaled from the supplied initial camera height above the fitted plane.",

            "The estimate assumes the visible reference surface is approximately static and planar.",

            "Do not use this output for navigation, obstacle avoidance, or regulatory altitude reporting.",

        ],

    }

    summary_path = Path(args.summary_json)

    summary_path.parent.mkdir(parents=True, exist_ok=True)

    summary_path.write_text(json.dumps(summary, indent=2), encoding="utf-8")


    print(json.dumps(summary, indent=2))

    print(f"Wrote {output_csv}")

    print(f"Wrote {summary_path}")



if __name__ == "__main__":

    main()




Monday, October 12, 2026

Continued from previous post

 A provider-neutral PoseProvider contract would give DVSA the greatest architectural benefit. The request could carry sensor assets, rig and calibration identifiers, synchronization metadata, navigation priors, requested processing mode, and optional dynamic masks; the response could carry a timestamped SE(3) trajectory, covariance or quality fields, landmark and loop-closure metadata, calibration corrections, diagnostics, and artifact references. A separate GeoRegistrationProvider could align that trajectory to ENU, NED, ECEF, or a site frame, and a GroundingService could combine poses with detections, depth, tracks, zones, and maps. This separation would make GroundedSLAM one implementation of geometric estimation rather than a new organizing principle for every DVSA subsystem.

RoboCap’s transferable lesson is that commodity vision becomes metrically useful only when the surrounding acquisition and estimation contracts are treated as measurement infrastructure. Multiple inexpensive cameras do not by themselves produce grounded video; synchronization, per-device calibration, exposure behavior, inertial characterization, observable baseline, session-level correction, loop closure, and offline refinement determine whether pixels can be assigned defensible positions over time. For drone fleet delivery and AirData-adjacent workflows, the highest-value customization is consequently not the cap’s hand-tracking model or near-field stereo geometry, but a drone-calibrated visual-inertial pose service whose outputs are fused with aircraft telemetry, georeferenced with explicit uncertainty, linked to DVSA’s semantic events, and summarized into fleet and flight records without entering the safety-critical control path.



Sunday, October 11, 2026

Continued from previous post

 Metric scale deserves equally careful treatment. RoboCap’s stereo baselines are 86.8 mm and 106.2 mm and are optimized for arm-length distances, while delivery-drone observations commonly span tens or hundreds of meters. Stereo depth uncertainty increases approximately with the square of distance and decreases with focal length and baseline, so a RoboCap-sized baseline cannot be assumed to yield useful absolute depth at aerial ranges. Drone customization would therefore combine a wider airframe-appropriate stereo baseline, higher-resolution or longer-focal-length imagery, tightly synchronized GNSS and inertial data, barometric altitude, laser or radar altitude where available, and terrain or map constraints. GroundedSLAM’s stereo mechanism could establish local metric structure, while GNSS and other navigation measurements could georeference and stabilize it over route-scale distances.

The distinction between local SLAM coordinates and Earth-referenced coordinates is fundamental for DVSA. GroundedSLAM reports a trajectory in an internally consistent world frame aligned to estimated gravity; a drone fleet platform generally requires latitude, longitude, ellipsoidal or orthometric altitude, and known uncertainty. A georeferencing layer could estimate a time-varying transform between the SLAM world frame, the aircraft body frame, the gimbal frame, and a navigation frame such as ENU or NED. GNSS position, GNSS quality indicators, autopilot attitude, gimbal telemetry, ground-control points, surveyed delivery sites, and map correspondences could become factors or post-processing constraints. The resulting record should retain both the native SLAM pose and the georeferenced pose, because forcing all estimates into one coordinate system can conceal whether an error arose from visual tracking, calibration, navigation telemetry, or map alignment.

Time synchronization would be the first integration contract. Commodity video often carries container timestamps that reflect encoding or arrival rather than exposure, while flight logs, GNSS receivers, gimbals, companion computers, and cameras may use different clocks. RoboCap avoids much of this problem by triggering all cameras from one signal and timestamping them in a common clock domain. A drone-oriented implementation could use hardware triggers and pulse-per-second synchronization where the payload supports them, Precision Time Protocol on capable onboard networks, and an estimated clock-offset-and-drift model when only software timestamps are available. DVSA should preserve exposure start or midpoint, sensor time, ingest time, clock source, offset estimate, drift estimate, and synchronization confidence rather than reducing timing to a single timestamp.

The immediate DVSA output of this layer would be a pose stream rather than a replacement video. For each frame or selected keyframe, the stream could contain a timestamp, position, orientation quaternion, velocity, gravity vector, covariance or confidence surrogate, current calibration identifier, tracking state, contributing cameras, loop-closure state, and links to the source flight and media objects. Depth products could be attached separately as rectified stereo metadata, disparity or depth maps, sparse landmarks, point clouds, and validity masks. The public Grounded API material states that processed sessions can produce metric camera trajectories, SLAM, depth maps, and interactive Rerun outputs, but public documentation reviewed here does not expose a stable schema or endpoint contract.

DVSA’s existing decomposition is compatible with this role. Its video domain manages media and account-scoped entities; analytics routines already cover optical flow, homography, tracking, clustering, tiled detection, and pluggable detection models; observability records correlated events; Azure services provide storage, indexing, retrieval, and agentic reasoning; and its agent and streaming layers can orchestrate asynchronous processing. GroundedSLAM or an equivalent adapter could be introduced as a pose provider behind a narrow interface, leaving ingestion, detection, indexing, and reasoning unchanged. That boundary would permit a hosted Grounded API implementation, a local vendor binary, and open alternatives to be evaluated against the same flight corpus without embedding vendor-specific semantics in DVSA’s core models.

Spatio-temporal grounding would then proceed by composition. A detector returns a two-dimensional image observation at frame time; the camera model maps the observation to a viewing ray; depth or multiview triangulation supplies a three-dimensional point or volume in the camera frame; the calibrated camera-to-body and SLAM pose transforms place it in the flight frame; and georeferencing places it in an Earth or site frame. A tracker associates successive observations into an entity track, while uncertainty propagation prevents a visually precise bounding box from being presented as a precise geographic location when depth, synchronization, or pose is weak. In compact form, the spatial operation is a chain such as world_from_object = world_from_body × body_from_gimbal × gimbal_from_camera × camera_from_object, with each transform timestamped and accompanied by provenance.

This composition can improve DVSA’s current use of homography without displacing it. A planar homography remains efficient for approximately planar scenes, stabilized nadir views, image registration, and map mosaics; SLAM becomes useful when relief, oblique views, altitude changes, parallax, repeated passes, or camera translation violate a single-plane model. The system could choose among telemetry-only projection, homography, stereo depth, sparse SLAM landmarks, and dense depth according to scene geometry and available sensors. The selected method and its residuals should be stored with the derived observation, enabling downstream search and reasoning to distinguish a map-aligned estimate from a purely visual track.

Delivery fleets create several domain-specific requirements absent from the RoboCap study. Routes are longer, often repeat the same corridors, and can contain visually self-similar roofs, roads, vegetation, warehouses, and suburban developments. GroundedSLAM’s authors report weaker loop-closure recall on long self-similar loops and in featureless halls, and identify place recognition rather than the estimator as the limiting component in those cases. A delivery customization could use route priors, GNSS-gated place retrieval, geofenced candidate loops, seasonal and illumination-robust place descriptors, downward and oblique camera ensembles, and known depot or delivery-pad landmarks. GNSS gating would reduce false closures between similar sites, while visual closure could bridge short GNSS degradations near buildings or under canopy.

Flight dynamics also differ from head motion. The reported patch tracker can fail under rotation above roughly 500 degrees per second, and the authors downsample camera images to at most 1000 pixels wide because their VGA-oriented tracker loses tracks at full resolution under blur and low light. Delivery aircraft normally operate below that rotation rate in stable cruise, but vibration, rapid yaw, aggressive avoidance, propeller shadows, rain, low sun, and gimbal slews can produce related effects. Drone adaptation could use exposure-aware motion prediction, IMU-seeded optical flow, vibration filtering, adaptive resolution, camera-specific masks, blur scoring, and a flight-mode-aware divergence detector. A nadir navigation camera, an oblique inspection camera, and a delivery-bay camera need not share the same tracking resolution or feature-selection policy even when they feed one estimator.[^1]

Dynamic-scene handling needs explicit attention. RoboCap’s estimator is designed to tolerate the wearer’s hands occupying parts of the view, but a drone scene may include moving vehicles, pedestrians, trees, water, clouds, shadows, and other aircraft. DVSA’s detectors and motion routines could generate dynamic masks so that SLAM favors static infrastructure, terrain, road markings, roofs, and fixed delivery fixtures. The masking policy should remain probabilistic: removing every pixel labeled as a vehicle could discard useful parked vehicles, while retaining moving objects as static landmarks can distort pose. A robust estimator could combine semantic priors, epipolar residuals, track consistency, and observed object velocity before accepting a feature as a mapping landmark.

A delivery proof-of-service model could use the grounded trajectory to associate package-transfer evidence with a defined delivery zone and time interval. The evidence record could link the command event, aircraft and payload identifiers, camera pose, package or marker detection, descent and hover state, winch or door telemetry, depth estimate, and a short signed media segment. The system could express that the package was visually observed within a site-relative volume under stated confidence, rather than infer successful delivery from a single detector output. Privacy controls would be needed to minimize retained imagery outside the delivery zone, redact people and license plates where policy requires, and separate operational evidence from broadly searchable visual content.

The same representation could support corridor-change detection and exception review. Repeated flights could align current keyframes with a site or route map, allowing DVSA to compare infrastructure, vegetation encroachment, temporary obstacles, landing-zone occupancy, or changes around a delivery point. SLAM would provide viewpoint and spatial correspondence; DVSA’s detection, segmentation, retrieval, and reasoning services would provide semantic interpretation. A map lifecycle should distinguish an immutable per-flight reconstruction, a curated fleet map, and temporary observations, because indiscriminately merging every session can preserve moving objects or outdated geometry as if they were permanent.

For incident reconstruction, the most useful customization would be a dual-track state record. The primary autopilot trajectory and the independent vision-inertial trajectory would be stored separately and compared through residuals over time. Divergence could indicate GNSS multipath, clock misalignment, gimbal calibration error, dropped telemetry, visual tracking failure, or airframe motion inconsistent with logged attitude; it would not by itself identify which source is correct. This approach follows the attached commodity-device analysis, which treats independent trackers and cameras as supplemental evidence rather than authoritative flight-control components. It also matches GroundedSLAM’s own distinction between a causal estimate and a more accurate offline trajectory: the paper states that the online result is about twice as inaccurate because full-session refinement occurs only after capture.

That online-offline distinction should become an explicit DVSA product contract. An onboard or streaming pose can support preview, approximate scene indexing, camera steering, and operator awareness, but final geospatial evidence should be regenerated after flight using all frames, loop closures, refined calibration, and complete telemetry. Versioned results would identify the estimator build, calibration, input manifest, map version, and processing mode. When an offline trajectory changes a previously indexed location, DVSA could supersede rather than overwrite the earlier record, preserving auditability and allowing downstream AirData integrations to display both operational and post-processed interpretations.

AirData UAV is primarily a flight-log and fleet-management environment rather than a raw multiview SLAM processor. Its documented API is REST-based; Enterprise access can query flights, and the Flight Upload API lets applications upload logs. AirData describes full telemetry replay and integrations spanning many aircraft and flight apps, including altitude, position, pilot, conditions, control inputs, battery data, warnings, and aircraft behavior. This makes flight identity, equipment identity, pilot, route, maintenance, and telemetry natural integration anchors, while large video, depth, point-cloud, and feature products would more appropriately remain in DVSA or object storage.

A practical AirData integration could associate one DVSA analysis session with an AirData flight identifier and equipment identifiers, then publish compact derived events rather than dense geometry. Suitable records could include a visual-trajectory quality summary, GNSS-versus-visual residual statistics, intervals of tracking loss, suspected calibration changes, geotagged delivery evidence, route-deviation evidence, and links to governed DVSA media or 3D views. AirData’s API can return flights filtered by time, location, pilot, drone, or battery, and its exports and operational views already organize telemetry and equipment context. The exact mechanism for attaching third-party analytic events or media should be validated with AirData because the public documentation reviewed here emphasizes flight retrieval and upload and does not document a general SLAM-result ingestion resource.

For fleet-wide health analysis, SLAM diagnostics could be aggregated by aircraft, payload, camera, mount, firmware, route, and environmental condition. Increasing reprojection residuals, declining stereo-match coverage, repeated self-calibration corrections, camera-to-IMU timing shifts, or a growing difference between autopilot and visual attitude could become maintenance indicators. Such statistics would require baseline distributions for each hardware configuration; RoboCap’s fleet numbers cannot be transferred directly to drones because baseline, optics, vibration, temperature range, altitude, and scene distance differ. DVSA’s observability model is suited to recording these diagnostics as correlated events, while AirData could retain the resulting fleet-level condition or maintenance annotations where supported.

Hardware profiles would allow the same software to span commodity devices without pretending that all inputs are equivalent. A minimum monocular profile could combine one calibrated video stream, IMU, and flight telemetry, yielding scale primarily from navigation data and producing lower-confidence geometry. A preferred stereo-inertial profile could use synchronized global-shutter cameras with a drone-appropriate baseline and hardware time synchronization. A richer profile could add a nadir camera, oblique context cameras, RTK GNSS, barometer, rangefinder or lidar, and gimbal encoders. Each profile would declare observability limits, expected depth range, rolling-shutter status, calibration method, synchronization quality, and supported online and offline products.

The sensor package should remain supplemental unless separately engineered and approved for safety-critical use. The attached commodity-device analysis notes that independent cameras and trackers can add recovery, audit, and incident evidence but generally should not be treated as primary navigation, flight-control, or certified safety systems. GroundedSLAM’s public report evaluates trajectory accuracy on research benchmarks, not aviation assurance, deterministic worst-case behavior, environmental qualification, cybersecurity, or regulatory compliance. Its published results therefore support technical evaluation for analytics and reconstruction, not substitution for the aircraft’s navigation or control stack.

The reported benchmark evidence is relevant but narrower than a delivery-fleet acceptance case. On LaMAria, a head-worn city-scale benchmark containing 63 test recordings, 27.5 hours, and 76 km, the reported method obtained an average control-point score of 62.3, compared with 24.2 for the best non-Aria alternative assembled by category; Aria’s own manufacturer system scored 75.9 and was treated as a reference rather than part of the ranking. The report also describes results on TUM-VI, Monado, Aria datasets, EuRoC, and VECtor, and identifies low light, fast motion, featureless corridors, long self-similar loops, and incomplete loop recognition as residual weaknesses. These results justify a drone-specific trial, but not an expectation that benchmark ordering will remain unchanged under altitude, vibration, rolling shutter, long-range geometry, weather, and repeated delivery routes.

An evaluation corpus for DVSA could therefore stratify flights by sensor profile, altitude, speed, camera attitude, time of day, weather, vibration level, scene type, GNSS quality, route repetition, and dynamic-object density. Ground truth could combine RTK/PPK trajectories, surveyed control points and delivery pads, photogrammetric checks, synchronized autopilot logs, and known camera-to-body calibration. Metrics would include absolute and relative trajectory error, orientation error, scale drift, geolocation error for detected objects, tracking availability, false loop closures, reinitialization frequency, calibration residual, online-to-offline correction, processing latency, compute cost, and storage amplification. Acceptance thresholds should be defined per application, because post-flight route reconstruction, delivery-zone evidence, live operator assistance, and safety-related navigation have different latency and accuracy requirements.

The most conservative implementation path would begin with offline enrichment. DVSA would ingest an immutable manifest containing camera streams, IMU, autopilot telemetry, gimbal telemetry, and calibration; validate timestamps and decode integrity; run the pose provider; align the trajectory to the navigation frame; project selected detections and tracks into three dimensions; and index compact spatial-temporal entities with provenance and uncertainty. Existing Celery, streaming, Databricks, Azure storage and search, commentary events, and agent orchestration could then schedule and query the output without coupling the rest of the platform to GroundedSLAM. After a representative fleet corpus establishes failure boundaries, a causal service could be added for provisional annotations while keeping the offline result authoritative for analytics.

Several safeguards would keep that pipeline reproducible. Input media and telemetry should be content-addressed; calibration and clock models should be immutable versioned objects; pose outputs should record software and hardware versions; every world-space observation should retain its source pixels and transform chain; and uncertainty should survive indexing rather than being flattened into a point. Quality gates could quarantine sessions with insufficient parallax, weak stereo overlap, excessive rolling-shutter distortion, poor time alignment, implausible bias estimates, unbounded scale, or unsupported camera modes. Human review could focus on consequential events and large residuals instead of inspecting entire flights.

A provider-neutral PoseProvider contract would give DVSA the greatest architectural benefit. The request could carry sensor assets, rig and calibration identifiers, synchronization metadata, navigation priors, requested processing mode, and optional dynamic masks; the response could carry a timestamped SE(3) trajectory, covariance or quality fields, landmark and loop-closure metadata, calibration corrections, diagnostics, and artifact references. A separate GeoRegistrationProvider could align that trajectory to ENU, NED, ECEF, or a site frame, and a GroundingService could combine poses with detections, depth, tracks, zones, and maps. This separation would make GroundedSLAM one implementation of geometric estimation rather than a new organizing principle for every DVSA subsystem.