openharmony 鸿蒙 rotation-control-guide-sys

2026-08-25 浏览 (1)

设备转动控制开发指南(仅对系统应用开放)

从API version 20开始,支持使用机械体设备控制器,提供更丰富的拍摄体验,如控制设备转动(仅限系统应用)。

使用手机作为控制终端,可以通过精确的参数设置调整云台或机械臂等设备的角度和运动轨迹,帮助快速构建控制机械体设备的应用。

接口介绍

机械体设备管理公开API接口使用指导请参见MechanicManager API参考

机械体设备管理系统API接口使用指导请参见MechanicManager API参考

接口名描述
on(type: 'attachStateChange', callback: Callback<AttachStateChangeInfo>): void注册attachStateChange事件的回调监听,等待连接状态变化。
说明:从API version 20开始支持。
off(type: 'attachStateChange', callback?: Callback<AttachStateChangeInfo>): void取消注册attachStateChange事件的回调监听。
说明:从API version 20开始支持。
getAttachedMechDevices(): MechInfo[]获取已连接的机械体设备列表。
说明:从API version 20开始支持。
setUserOperation(operation: Operation, mac: string, params: string): void设置用户操作。
说明:从API version 20开始支持。
setCameraTrackingEnabled(isEnabled: boolean): void启用或禁用摄像头跟踪。
说明:从API version 20开始支持。
getCameraTrackingEnabled(): boolean检查是否启用了摄像头跟踪。
说明:从API version 20开始支持。
getCameraTrackingLayout(): CameraTrackingLayout获取此机械体设备摄像头跟踪布局。
说明:从API version 20开始支持。
rotate(mechId: number, angles: RotationAngles, duration: number): Promise<Result>将机械体设备旋转到相对角度。
说明:从API version 20开始支持。
rotateToEulerAngles(mechId: number, angles: EulerAngles, duration: number): Promise<Result>将机械体设备旋转到绝对角度。
说明:从API version 20开始支持。
getMaxRotationTime(mechId: number): number获取机械体设备的最大连续旋转持续时间。
说明:从API version 20开始支持。
getMaxRotationSpeed(mechId: number): RotationSpeed获取机械体设备的最大旋转速度。
说明:从API version 20开始支持。
stopMoving(mechId: number): Promise<void>停止机械体设备的移动。
说明:从API version 20开始支持。
getCurrentAngles(mechId: number): EulerAngles获取机械体设备的当前角度。
说明:从API version 20开始支持。
getRotationLimits(mechId: number): RotationLimits获取指定机械体设备相对于参考点的最大旋转角度。
说明:从API version 20开始支持。
getRotationAxesStatus(mechId: number): RotationAxesStatus获取旋转轴的状态。
说明:从API version 20开始支持。
on(type: 'rotationAxesStatusChange', callback: Callback<RotationAxesStateChangeInfo>): void注册rotationAxesStatusChange事件的回调监听。
说明:从API version 20开始支持。
off(type: 'rotationAxesStatusChange', callback?: Callback<RotationAxesStateChangeInfo>): void取消注册rotationAxesStatusChange事件的回调监听。
说明:从API version 20开始支持。

开发步骤

开发准备

  1. 一台支持Mechanic Kit协议的机械体设备。
  2. 若要验证智能跟踪功能,主设备的摄像头驱动需要支持人脸检测功能。
  3. 更新SDK到API 20或以上,具体操作参见更新指南
  4. 机械体设备与主设备完成蓝牙连接状态。

管理设备连接状态

管理设备连接状态,确保设备连接或断开时应用及时响应。

  1. 导入机械体设备管理模块。

    import { mechanicManager } from '@kit.MechanicKit';
    
  2. 获取已连接的机械体设备列表。

    let savedMechanicIds: number[] = [];
    
    try {
    const devices = mechanicManager.getAttachedMechDevices();
    console.info('Connected devices:', devices);
    
    devices.forEach(device => {
        console.info(`Device ID: ${device.mechId}`);
        console.info(`Device Name: ${device.mechName}`);
        console.info(`Device Type: ${device.mechDeviceType}`);
    
    //保存设备类型为 GIMBAL_DEVICE 的设备的 MechId。
        if (device.mechDeviceType === mechanicManager.MechDeviceType.GIMBAL_DEVICE) {
        savedMechanicIds.push(device.mechId);
        console.info(`GIMBAL_TYPE device saved ID: ${device.mechId}`);
        } else {
        console.info(`Skip non-gimbal devices: ${device.mechId}`);
        }
    });
    
    console.info('List of saved gimbal device IDs:', savedMechanicIds);
    } catch (err) {
    console.error('Error getting attached devices:', err);
    }
    
  3. 监听设备的连接状态。

    const attachStateChangeCallback = (info: mechanicManager.AttachStateChangeInfo) => {
        if (info.state === mechanicManager.AttachState.ATTACHED) {
            console.info('Device attached:', info.mechInfo);
            // 处理设备连接逻辑
        } else if (info.state === mechanicManager.AttachState.DETACHED) {
            console.info('Device detached:', info.mechInfo);
            // 处理设备断开逻辑
        }
    };
    // 注册监听
    mechanicManager.on('attachStateChange', attachStateChangeCallback);
    
  4. 处理设备连接与断开的事件。

    const savedMechanicIds: number[] = [];
    const attachStateChangeCallback = (info: mechanicManager.AttachStateChangeInfo) => {
        if (info.state === mechanicManager.AttachState.ATTACHED) {
            console.info('Device attached:', info.mechInfo);
            savedMechanicIds.push(info.mechInfo.mechId);
            // To do sth.
        } else if (info.state === mechanicManager.AttachState.DETACHED) {
            console.info('Device detached:', info.mechInfo);
            savedMechanicIds.filter(id => id !== info.mechInfo.mechId);
            // To do sth.
        }
    };
    // 注册监听
    mechanicManager.on('attachStateChange', attachStateChangeCallback);
    
  5. 取消监听操作。

    const savedMechanicIds: number[] = [];
    const attachStateChangeCallback = (info: mechanicManager.AttachStateChangeInfo) => {
        if (info.state === mechanicManager.AttachState.ATTACHED) {
            console.info('Device attached:', info.mechInfo);
            savedMechanicIds.push(info.mechInfo.mechId);
            // To do sth.
        } else if (info.state === mechanicManager.AttachState.DETACHED) {
            console.info('Device detached:', info.mechInfo);
            savedMechanicIds.filter(id => id !== info.mechInfo.mechId);
            // To do sth.
        }
    };
    // 取消特定回调的监听
    mechanicManager.off('attachStateChange', attachStateChangeCallback);
    

控制设备转动

精准控制机械体设备转动,如角度调整和运动轨迹控制等,帮助开发者实现灵活的机械体设备操作功能。

  1. 查询设备当前状态及其限制条件。

    try {
        const savedMechanicIds: number[] = [];
        // 初始化设备功能,例如获取设备状态
        const devices = mechanicManager.getAttachedMechDevices();
        console.info('Connected devices:', devices);
    
        devices.forEach(device => {
            console.info(`Device ID: ${device.mechId}`);
            console.info(`Device Name: ${device.mechName}`);
            console.info(`Device Type: ${device.mechDeviceType}`);
            savedMechanicIds.push(device.mechId);
        });
    
        // 注册设备连接状态监听
        const attachStateChangeCallback = (info: mechanicManager.AttachStateChangeInfo) => {
            if (info.state === mechanicManager.AttachState.ATTACHED) {
                console.info('Device attached:', info.mechInfo);
            } else if (info.state === mechanicManager.AttachState.DETACHED) {
                console.info('Device detached:', info.mechInfo);
            }
        };
        mechanicManager.on('attachStateChange', attachStateChangeCallback);
        // 获取当前角度
        const currentAngles = mechanicManager.getCurrentAngles(savedMechanicIds[0]);
        console.info('current angle:', currentAngles);
    
        // 获取旋转限制
        const rotationLimits = mechanicManager.getRotationLimits(savedMechanicIds[0]);
        console.info('Rotation limit:', rotationLimits);
    
        // 获取最大旋转速度
        const maxSpeed = mechanicManager.getMaxRotationSpeed(savedMechanicIds[0]);
        console.info('Maximum rotation speed:', maxSpeed);
    
        // 获取速度控制最大持续时间
        const maxTime = mechanicManager.getMaxRotationTime(savedMechanicIds[0]);
        console.info('Maximum spin time:', maxTime);
    } catch (err) {
        console.error('Failed to query device status:', err);
    }
    
  2. 执行相对角度的旋转控制,以调整设备的位置。

    const savedMechanicIds: number[] = [];
    // 初始化设备功能,例如获取设备状态
    const devices = mechanicManager.getAttachedMechDevices();
    console.info('Connected devices:', devices);
    
    devices.forEach(device => {
        savedMechanicIds.push(device.mechId);
    });
    //在执行转动控制之前,需要先关闭跟踪拍摄功能。
    mechanicManager.setCameraTrackingEnabled(false);
    
    try {
        const mechId = savedMechanicIds[0]; // 设备ID
    
        // 查询当前角度
        const currentAngles = mechanicManager.getCurrentAngles(mechId);
        if (!currentAngles||currentAngles.yaw === undefined||currentAngles.pitch === undefined||
            currentAngles.roll === undefined) {
            console.error('Failed to retrieve current angles or angles are undefined.');
            return;
        }
    
        // 获取旋转限制
        const rotationLimits = mechanicManager.getRotationLimits(mechId);
        if (!rotationLimits||rotationLimits.negativeYawMax === undefined||
            rotationLimits.positiveYawMax === undefined||
            rotationLimits.negativePitchMax === undefined||rotationLimits.positivePitchMax === undefined||
            rotationLimits.negativeRollMax === undefined||rotationLimits.positiveRollMax === undefined) {
            console.error('Failed to retrieve rotation limits or limits are undefined.');
            return;
        }
        console.info('Rotation limits:', rotationLimits);
    
        // 定义目标角度并确保类型正确
        const angles: mechanicManager.RotationAngles = {
            yaw: Math.PI / 4, // 偏航角:45度
            pitch: Math.PI / 6, // 俯仰角:30度
            roll: 0            // 横滚角:0度
        };
    
        // 检查目标角度是否超出限位
        if (currentAngles.yaw + (angles.yaw ?? 0) > rotationLimits.negativeYawMax||
            currentAngles.yaw + (angles.yaw ?? 0) < rotationLimits.positiveYawMax||
            currentAngles.pitch + (angles.pitch ?? 0) > rotationLimits.negativePitchMax||
            currentAngles.pitch + (angles.pitch ?? 0) < rotationLimits.positivePitchMax||
            currentAngles.roll + (angles.roll ?? 0) > rotationLimits.negativeRollMax||
            currentAngles.roll + (angles.roll ?? 0) < rotationLimits.positiveRollMax
        ) {
            console.error('Target angles exceed rotation limits.');
            return;
        }
    
        const duration = 2000; // 旋转持续时间:2秒
    
        // 执行旋转
        mechanicManager.rotate(mechId, angles, duration)
            .then((result) => {
                console.info(`Rotation Result: ${result}`);
            });
    } catch (err) {
        console.error('Failed to rotate relative angle:', err);
    }
    
  3. 以指定速度持续转动,直至任务完成。

    try {
        const savedMechanicIds: number[] = [];
        // 初始化设备功能,例如获取设备状态
        const devices = mechanicManager.getAttachedMechDevices();
        console.info('Connected devices:', devices);
    
        devices.forEach(device => {
            savedMechanicIds.push(device.mechId);
        });
    
        const mechId = savedMechanicIds[0]; // 假设使用第一个设备
    
        // 获取速度控制最大持续时间
        const maxTime = mechanicManager.getMaxRotationTime(mechId);
        console.info('Maximum spin time:', maxTime);
    
        // 获取最大旋转速度
        const maxSpeed = mechanicManager.getMaxRotationSpeed(mechId);
        if (!maxSpeed||maxSpeed.yawSpeed === undefined||maxSpeed.pitchSpeed === undefined||
            maxSpeed.rollSpeed === undefined) {
            console.error('Failed to retrieve maximum rotation speed or speed values are undefined.');
            return;
        }
        console.info('Maximum rotation speed:', maxSpeed);
        // 定义旋转速度和持续时间
        const speed: mechanicManager.RotationSpeed = {
            yawSpeed: maxSpeed.yawSpeed / 2, // 偏航速度:最大速度的一半
            pitchSpeed: maxSpeed.pitchSpeed / 2, // 俯仰速度:最大速度的一半
            rollSpeed: maxSpeed.rollSpeed / 2    // 横滚速度:最大速度的一半
        };
        const duration = Math.min(maxTime, 5000); // 持续时间:最多5秒
    
        // 执行旋转
        mechanicManager.rotateBySpeed(mechId, speed, duration)
            .then((result) => {
                console.info(`Rotation Result: ${result}`);
            });
    } catch (err) {
         console.error('Failed to rotate by speed:', err);
    }
    
  4. 监听旋转轴状态变化。

    const rotationAxesCallback = (info: mechanicManager.RotationAxesStateChangeInfo) => {
    console.info('Rotation Axes state change:', info);
    const mechId = info.mechId;
    const status = info.status;
    
    console.info(`Device ${mechId} status update:`);
    console.info(`- Yaw  axes enabled: ${status.yawEnabled}`);
    console.info(`- Pitch axes enabled: ${status.pitchEnabled}`);
    console.info(`- Roll axes enabled: ${status.rollEnabled}`);
    
    if (status.yawLimited !== undefined) {
        console.info(`- Yaw axis restriction state: ${status.yawLimited}`);
    }
    };
    
    // 注册监听
    mechanicManager.on('rotationAxesStatusChange', rotationAxesCallback);
    
  5. 停止设备运动。

    try {
        const savedMechanicIds: number[] = [];
        // 初始化设备功能,例如获取设备状态
        const devices = mechanicManager.getAttachedMechDevices();
        console.info('Connected devices:', devices);
    
        devices.forEach(device => {
            savedMechanicIds.push(device.mechId);
        });
        const mechId = savedMechanicIds[0];
        mechanicManager.stopMoving(mechId);
        console.info('The device has ceased moving.');
    } catch (err) {
        console.error('Failed to stop device movement:', err);
    }
    

调试验证

为了确保机械体设备管理功能正常,按以下步骤进行调试验证:

建立连接

  1. 确保机械体设备与开发设备通过蓝牙配对并连接。
  2. 将开发设备放置在机械体设备上,确保两者正确连接。

功能验证步骤

  1. 设备列表查询:调用 getAttachedMechDevices 接口查询当前已连接的机械体设备列表,并验证机械体设备是否正确识别。
  2. 设备转动控制:调用 setCameraTrackingEnabled 关闭跟踪功能,并通过 getCameraTrackingEnabled 验证状态;调用 rotaterotateBySpeed 控制机械体设备转动。

验证结果说明

  • 如果 getAttachedMechDevices 返回包含机械体设备信息的列表,表示设备识别正常。
  • 如果调用 rotaterotateBySpeed 后设备按预期开始转动,表示设备转动正常。

你可能感兴趣的鸿蒙文章

openharmony 鸿蒙 camera-tracking-guide

openharmony 鸿蒙 Readme-CN

openharmony 鸿蒙 mechanic-kit-intro

  • 所属分类: 后端技术
  • 本文标签: 软件 鸿蒙
  • 版权声明: 本文链接 https://seaxiang.com/blog/4loDCW4U