跳过导航,直接进入主要内容跳过导航,直接进入主要内容跳过导航,直接进入主要内容

PTZ 服务:虚拟云台状态机

不需要电机。PtzState 是一个纯状态机,让固定机位像云台机一样可被 控制——位置、速度、预置位,以及 tick 驱动的运动模拟。

安装

cargo add onvif-device-rs@0.7.0  # crate 名与仓库(onvif-rs)不同

状态机

use onvif_device_rs::ptz_state::{PtzState, Position, Velocity, Preset};

let state = std::sync::Arc::new(PtzState::new());

state.absolute_move(Position { x: 0.8, y: 0.2, zoom: 0.5 }); // 缓动趋向目标
state.continuous_move(Velocity { x: 0.1, y: 0.0, zoom: 0.0 }); // 随 tick 积分
state.stop();
state.relative_move(Velocity { x: -0.1, y: 0.05, zoom: 0.0 });
state.tick(100); // 推进模拟 dt 毫秒

let Position { x, y, zoom } = state.get_position();
let status = state.get_status();        // "IDLE" | "MOVING"
let token = state.save_preset("大门");  // 返回预置位 token
state.goto_preset(&token);
let presets: Vec<Preset> = state.list_presets();
  • ContinuousMove 按 tick 积分速度;AbsoluteMove 最多 20 个 tick 缓动到目标;状态为 IDLE/MOVING。
  • 坐标是归一化值:水平/垂直 [-1, 1]、变焦 [0, 1]——在客户端或 UI 侧映射为真实角度。
  • tick 挂在任何你方便的循环上(定时任务、渲染循环)。

接线

一个 PtzHandler 服务全部十一个 PTZ 动作:

use onvif_device_rs::ptz::PtzHandler;

for action in [
    "ContinuousMove", "AbsoluteMove", "RelativeMove", "Stop",
    "GetStatus", "GetPresets", "SetPreset", "GotoPreset",
    "RemovePreset", "GetNodes", "GetConfigurations",
] {
    soap.register_handler(action, Box::new(PtzHandler(std::sync::Arc::clone(&state))));
}

examples/ptz_demo.rs 对活服务器跑全动词集——绝对移动精确落位、 连续移动随 tick 漂移、预置位往返——带断言,退出码 0。

真电机

PtzState 是完整的参考实现,不是硬性要求:有真实云台硬件的宿主把 同样的动作实现为自定义 [OnvifActionHandler],直接驱动电机。

可访问性增强功能已加载,支持焦点管理、键盘导航和屏幕阅读器