Table of Contents

Class PTZAutoTrackingController

Namespace
VisioForge.Core.AI.PTZ
Assembly
VisioForge.Core.AI.dll

Converts object-detection positions into continuous PTZ velocity commands so an ONVIF PTZ camera follows a tracked object. Implements a proportional control law with a centered dead zone, sticky target tracking, a lost-target timeout, and command rate limiting.

public sealed class PTZAutoTrackingController : IDisposable, IAsyncDisposable

Inheritance

Implements

Inherited Members

Remarks

Feed detections either by attaching to an VisioForge.Core.MediaBlocks.AI.ObjectAnalyticsBlock or VisioForge.Core.MediaBlocks.AI.YOLOObjectDetectorBlock (see the AttachTo overloads), or by calling VisioForge.Core.AI.PTZ.PTZAutoTrackingController.OnDetections(VisioForge.Core.Types.VideoProcessing.OnnxDetection[],System.Drawing.Size,System.TimeSpan) directly. Detections are consumed on the caller's thread; camera commands are actuated on a dedicated background worker so the detection thread is never blocked. Sticky tracking requires stable tracker identifiers, which VisioForge.Core.MediaBlocks.AI.ObjectAnalyticsBlock provides via ByteTrack; a plain detector without tracking reacquires a target every frame.

Constructors

PTZAutoTrackingController(PTZAutoTrackingSettings, IPTZMoveTransport)

Initializes a new instance of the VisioForge.Core.AI.PTZ.PTZAutoTrackingController class.

public PTZAutoTrackingController(PTZAutoTrackingSettings settings, IPTZMoveTransport transport)

Parameters

settings PTZAutoTrackingSettings

The tracking settings. Must not be null and must validate.

transport IPTZMoveTransport

The PTZ transport to actuate. Must not be null.

Exceptions

ArgumentNullException

Thrown when an argument is null.

ArgumentException

Thrown when settings fails validation (see VisioForge.Core.Types.X.AI.PTZAutoTrackingSettings.Validate).

Properties

CurrentTargetTrackerId

Gets the tracker identifier of the currently locked target, or -1 when no target is locked.

public int CurrentTargetTrackerId { get; }

Property Value

int

IsRunning

Gets a value indicating whether the controller is currently running.

public bool IsRunning { get; }

Property Value

bool

Methods

AttachTo(ObjectAnalyticsBlock, Size)

Attaches to an VisioForge.Core.MediaBlocks.AI.ObjectAnalyticsBlock, following the objects it reports. The frame size is the source resolution (in pixels) that the block's detection boxes are expressed in.

public void AttachTo(ObjectAnalyticsBlock block, Size frameSize)

Parameters

block ObjectAnalyticsBlock

The analytics block to follow. Must not be null.

frameSize Size

The source frame size in pixels.

Exceptions

ArgumentNullException

Thrown when block is null.

ObjectDisposedException

Thrown when the controller has been disposed.

AttachTo(YOLOObjectDetectorBlock, Size)

Attaches to a VisioForge.Core.MediaBlocks.AI.YOLOObjectDetectorBlock, following the objects it reports. Since a plain detector carries no tracker identifiers, the target is reacquired every frame per policy.

public void AttachTo(YOLOObjectDetectorBlock block, Size frameSize)

Parameters

block YOLOObjectDetectorBlock

The detector block to follow. Must not be null.

frameSize Size

The source frame size in pixels.

Remarks

Empty-frame limitation. VisioForge.Core.MediaBlocks.AI.YOLOObjectDetectorBlock raises OnObjectsDetected only for frames that yield at least one detection; it does not deliver an empty frame when the tracked object leaves the view. The controller therefore only reacts while objects are present on this path, so the halt-on-target-lost edge, the VisioForge.Core.Types.X.AI.PTZAutoTrackingSettings.LostTargetTimeout / VisioForge.Core.AI.PTZ.PTZAutoTrackingController.OnTargetLost transition, the home-preset recall, and the idle patrol are not driven when the frame goes empty — the last continuous move keeps running until the camera's own timeout.

Attach to an VisioForge.Core.MediaBlocks.AI.ObjectAnalyticsBlock instead when you need those behaviors: it reports every processed frame (including empty ones) and provides the stable tracker IDs sticky tracking relies on.

Exceptions

ArgumentNullException

Thrown when block is null.

ObjectDisposedException

Thrown when the controller has been disposed.

Dispose()

Synchronously tears down the controller. As a best effort it halts the camera: while the actuation worker is still alive it enqueues a final stop and waits a short bounded window (up to ~500 ms) for the worker to actuate it before cancelling, so a camera left in continuous motion does not keep panning until the device's own timeout. Because the worker is not joined, this method may return while a transport call is still in flight; a consumer that disposes/closes the transport immediately afterward must use VisioForge.Core.AI.PTZ.PTZAutoTrackingController.DisposeAsync instead, which awaits the worker within a bounded window so that in the normal case no call is outstanding. Prefer VisioForge.Core.AI.PTZ.PTZAutoTrackingController.DisposeAsync whenever an await is possible.

public void Dispose()

DisposeAsync()

Asynchronously tears down the controller: stops the actuation worker (cancelling immediately, so commands still queued at that point — such as a pending home or patrol preset — are not guaranteed to be actuated) and issues a final stop to halt the camera, then releases resources. This is the recommended teardown path — it awaits the worker within a bounded window (up to ~5 s) rather than the shorter fixed window VisioForge.Core.AI.PTZ.PTZAutoTrackingController.Dispose uses, so in the normal case no transport call is left in flight when it completes. Against an unresponsive camera (the transport takes no cancellation token) the join is time-bounded, so a call may still be in progress on the worker when it returns; a subsequent VisioForge.Core.AI.PTZ.PTZAutoTrackingController.Start serializes the next worker behind that one.

public ValueTask DisposeAsync()

Returns

ValueTask

A task that completes when the controller has fully stopped and released its resources.

OnDetections(OnnxDetection[], Size, TimeSpan)

Processes a single frame of detections and decides the next PTZ command. This is the direct entry point that the AttachTo overloads call.

public void OnDetections(OnnxDetection[] objects, Size frameSize, TimeSpan timestamp)

Parameters

objects OnnxDetection[]

The detections for this frame, in source-frame pixel coordinates.

frameSize Size

The source frame size in pixels.

timestamp TimeSpan

The source frame timestamp; used for the lost-target timeout and rate limiting.

Start()

Starts the controller and its actuation worker. Idempotent.

public void Start()

StopAsync()

Stops the controller: cancels the actuation worker, waits for it to finish within a bounded window, then issues a final stop to halt the camera. Cancellation is immediate, so commands still queued when VisioForge.Core.AI.PTZ.PTZAutoTrackingController.StopAsync is called (for example a home or patrol preset) are not guaranteed to be actuated; the explicit final stop deterministically halts any in-progress continuous move regardless. Both the worker join and the final stop are time-bounded so an unresponsive camera (the transport methods take no cancellation token) cannot hang teardown indefinitely.

public Task StopAsync()

Returns

Task

A task that completes when the worker has stopped and the camera has been halted.

OnMoveCommand

Raised for every command the controller decides to send to the camera (moves and stops), at the moment it is enqueued. Raised on the detection thread; intended for diagnostics and tests.

public event EventHandler<PTZMoveCommandEventArgs> OnMoveCommand

Event Type

EventHandler<PTZMoveCommandEventArgs>

OnPatrolPreset

Raised whenever the idle patrol moves to a preset. The argument is the preset token being recalled. Raised on the detection thread; intended for diagnostics and tests.

public event EventHandler<string> OnPatrolPreset

Event Type

EventHandler<string>

OnTargetAcquired

Raised when a new target is locked (a fresh acquisition, not on every frame). The argument is the detection that was selected. Raised on the detection thread.

public event EventHandler<OnnxDetection> OnTargetAcquired

Event Type

EventHandler<OnnxDetection>

OnTargetLost

Raised once when the current target has been absent for longer than VisioForge.Core.Types.X.AI.PTZAutoTrackingSettings.LostTargetTimeout. Raised on the detection thread.

public event EventHandler OnTargetLost

Event Type

EventHandler