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, IAsyncDisposableInheritance
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
settingsPTZAutoTrackingSettings-
The tracking settings. Must not be null and must validate.
transportIPTZMoveTransport-
The PTZ transport to actuate. Must not be null.
Exceptions
- ArgumentNullException
-
Thrown when an argument is null.
- ArgumentException
-
Thrown when
settingsfails 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
IsRunning
Gets a value indicating whether the controller is currently running.
public bool IsRunning { get; }Property Value
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
blockObjectAnalyticsBlock-
The analytics block to follow. Must not be null.
frameSizeSize-
The source frame size in pixels.
Exceptions
- ArgumentNullException
-
Thrown when
blockis 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
blockYOLOObjectDetectorBlock-
The detector block to follow. Must not be null.
frameSizeSize-
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
blockis 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
objectsOnnxDetection[]-
The detections for this frame, in source-frame pixel coordinates.
frameSizeSize-
The source frame size in pixels.
timestampTimeSpan-
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> OnMoveCommandEvent Type
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> OnPatrolPresetEvent Type
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> OnTargetAcquiredEvent 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