• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 设备转动控制开发指南
2<!--Kit: Mechanic Kit-->
3<!--Subsystem: Mechanic-->
4<!--Owner: @hobbycao-->
5<!--Designer: @saga2025-->
6<!--Tester: @zhaodengqi-->
7<!--Adviser: @foryourself-->
8
9从API version 20开始,支持使用机械设备管理。在视频录制和直播等应用场景中,开发者希望为拥有机械体配件设备的用户提供更丰富的拍摄体验,如控制机械体配件设备转动功能。
10
11拍摄控制,可以将手机作为控制终端,操控云台或机械臂等机械体配件设备进行精准的角度调整和运动轨迹控制,帮助开发者快速构建控制机械配件设备的应用。
12
13## 接口介绍
14
15机械设备管理公开API接口使用指导请参见[MechanicManager  API参考](../reference/apis-mechanic-kit/js-apis-mechanicManager.md)。
16机械设备管理系统API接口使用指导请参见[MechanicManager  API参考](../reference/apis-mechanic-kit/js-apis-mechanicManager-sys.md)。
17
18| 接口名                                                               | 描述                       |
19| -------------------------------------------------------------------- | -------------------------- |
20|on(type: 'attachStateChange', callback: Callback\<AttachStateChangeInfo>): void | 注册attachStateChange事件的回调监听,等待连接状态变化。<br>**说明**:从API version 20开始支持。|
21|off(type: 'attachStateChange', callback?: Callback\<AttachStateChangeInfo>): void | 取消注册attachStateChange事件的回调监听。<br>**说明**:从API version 20开始支持。|
22|getAttachedMechDevices(): MechInfo[] | 获取已连接的机械体设备列表。<br>**说明**:从API version 20开始支持。|
23|setUserOperation(operation: Operation, mac: string, params: string): void | 设置用户操作。<br>**说明**:从API version 20开始支持。|
24|setCameraTrackingEnabled(isEnabled: boolean): void | 启用或禁用摄像头跟踪。<br>**说明**:从API version 20开始支持。|
25|getCameraTrackingEnabled(): boolean | 检查是否启用了摄像头跟踪。<br>**说明**:从API version 20开始支持。|
26|getCameraTrackingLayout(): CameraTrackingLayout | 获取此机械设备摄像头跟踪布局。<br>**说明**:从API version 20开始支持。|
27|rotate(mechId: number, angles: RotationAngles, duration: number): Promise\<Result> | 将机械体设备旋转到相对角度。<br>**说明**:从API version 20开始支持。|
28|rotateToEulerAngles(mechId: number, angles: EulerAngles, duration: number): Promise\<Result> | 将机械体设备旋转到绝对角度。<br>**说明**:从API version 20开始支持。|
29|getMaxRotationTime(mechId: number): number | 获取机械体设备的最大连续旋转持续时间。<br>**说明**:从API version 20开始支持。|
30|getMaxRotationSpeed(mechId: number): RotationSpeed | 获取机械设备的最大旋转速度。<br>**说明**:从API version 20开始支持。|
31|stopMoving(mechId: number): Promise\<void> | 停止机械体设备的移动。<br>**说明**:从API version 20开始支持。|
32|getCurrentAngles(mechId: number): EulerAngles | 获取机械体设备的当前角度。<br>**说明**:从API version 20开始支持。|
33|getRotationLimits(mechId: number): RotationLimits | 获取指定机械体设备相对于参考点的最大旋转角度。<br>**说明**:从API version 20开始支持。|
34|getRotationAxesStatus(mechId: number): RotationAxesStatus | 获取旋转轴的状态。<br>**说明**:从API version 20开始支持。|
35|on(type: 'rotationAxesStatusChange', callback: Callback\<RotationAxesStateChangeInfo>): void | 注册rotationAxesStatusChange事件的回调监听。<br>**说明**:从API version 20开始支持。|
36|off(type: 'rotationAxesStatusChange', callback?: Callback\<RotationAxesStateChangeInfo>): void | 取消注册rotationAxesStatusChange事件的回调监听。<br>**说明**:从API version 20开始支持。|
37
38## 开发步骤
39
40### 开发准备
41
421. 一台支持MechanicKit协议的机械体配件设备。
43
442. 机械体配件设备与开发设备完成蓝牙连接。
45
46### 管理设备连接状态
47
48动态管理设备连接状态,确保设备连接或断开时应用能及时响应。
49
501. 导入机械设备管理模块文件。
51
52    ```ts
53    import mechanicManager from '@kit.MechanicKit';
54    ```
55
562. 获取已连接的机械设备列表。
57
58    ```ts
59    let savedMechanicIds: number[] = [];
60
61    try {
62    const devices = mechanicManager.getAttachedMechDevices();
63    console.log('Connected devices:', devices);
64
65    devices.forEach(device => {
66        console.log(`Device ID: ${device.mechId}`);
67        console.log(`Device Name: ${device.mechName}`);
68        console.log(`Device Type: ${device.mechDeviceType}`);
69
70    //保存设备类型为GIMBAL_DEVICE的设备的MechId
71        if (device.mechDeviceType === mechanicManager.MechDeviceType.GIMBAL_DEVICE) {
72        savedMechanicIds.push(device.mechId);
73        console.log(`GIMBAL_TYPE device saved ID: ${device.mechId}`);
74        } else {
75        console.log(`Skip non-gimbal devices: ${device.mechId}`);
76        }
77    });
78
79    console.log('List of saved gimbal device IDs:', savedMechanicIds);
80    } catch (err) {
81    console.error('Error getting attached devices:', err);
82    }
83    ```
84
853. 监听设备连接状态变化。
86
87    ```ts
88    const attachStateChangeCallback = (info: mechanicManager.AttachStateChangeInfo) => {
89    if (info.state === mechanicManager.AttachState.ATTACHED) {
90        console.log('Device attached:', info.mechInfo);
91        // 处理设备连接逻辑
92        handleDeviceAttached(info.mechInfo);
93    } else if (info.state === mechanicManager.AttachState.DETACHED) {
94        console.log('Device detached:', info.mechInfo);
95        // 处理设备断开逻辑
96        handleDeviceDetached(info.mechInfo);
97    }
98    };
99
100    // 注册监听
101    mechanicManager.on('attachStateChange', attachStateChangeCallback);
102    ```
103
1044. 处理设备连接和断开事件。
105
106    ```ts
107    mechanicManager.on('attachStateChange', attachStateChangeCallback);
108
109    function handleDeviceAttached(mechInfo: mechanicManager.MechInfo) {
110    console.log(`New device is connected: ${mechInfo.mechName} (ID: ${mechInfo.mechId})`);
111    savedMechanicIds.push(mechInfo.mechId);
112    // To do sth.
113    }
114
115    function handleDeviceDetached(mechInfo:  mechanicManager.MechInfo) {
116    console.log(`Device disconnected: ${mechInfo.mechName} (ID: ${mechInfo.mechId})`);
117    savedMechanicIds.filter(id => id !== mechInfo.mechId);
118    // To do sth.
119    }
120    ```
121
1225. 取消监听。
123
124    ```ts
125    // 取消特定回调的监听
126    mechanicManager.off('attachStateChange', attachStateChangeCallback);
127    ```
128
129### 控制设备转动
130
131精准控制机械体配件设备转动,如角度调整和运动轨迹控制等,帮助开发者实现灵活的机械体配件设备操作功能。
132
1331. 查询设备当前状态和限制。
134
135    ```ts
136    try {
137    // 初始化设备功能,例如获取设备状态
138    const devices = mechanicManager.getAttachedMechDevices();
139    console.log('Connected devices:', devices);
140
141    devices.forEach(device => {
142        console.log(`Device ID: ${device.mechId}`);
143        console.log(`Device Name: ${device.mechName}`);
144        console.log(`Device Type: ${device.mechDeviceType}`);
145    });
146
147    // 注册设备连接状态监听
148    const attachStateChangeCallback = (info: mechanicManager.AttachStateChangeInfo) => {
149        if (info.state === mechanicManager.AttachState.ATTACHED) {
150        console.log('Device attached:', info.mechInfo);
151        } else if (info.state === mechanicManager.AttachState.DETACHED) {
152        console.log('Device detached:', info.mechInfo);
153        }
154    };
155    mechanicManager.on('attachStateChange', attachStateChangeCallback);
156    // 获取当前角度
157    const currentAngles = mechanicManager.getCurrentAngles(savedMechanicIds[0]);
158    console.log('current angle:', currentAngles);
159
160    // 获取旋转限制
161    const rotationLimits = mechanicManager.getRotationLimits(savedMechanicIds[0]);
162    console.log('Rotation limit:', rotationLimits);
163
164    // 获取最大旋转速度
165    const maxSpeed = mechanicManager.getMaxRotationSpeed(savedMechanicIds[0]);
166    console.log('Maximum rotation speed:', maxSpeed);
167
168    // 获取速度控制最大持续时间
169    const maxTime = mechanicManager.getMaxRotationTime(savedMechanicIds[0]);
170    console.log('Maximum spin time:', maxTime);
171    } catch (err) {
172    console.error('Failed to query device status:', err);
173    }
174    ```
175
1762. 执行相对角度旋转。
177
178    ```ts
179    //执行转动控制前需要先关闭跟踪拍摄功能
180    mechanicManager.setCameraTrackingEnabled(false);
181
182    async function rotateByRelativeAngles() {
183    try {
184        const mechId = savedMechanicIds[0]; // 设备ID
185
186        // 查询当前角度
187        const currentAngles = mechanicManager.getCurrentAngles(mechId);
188        if (!currentAngles || currentAngles.yaw === undefined || currentAngles.pitch === undefined ||
189        currentAngles.roll === undefined) {
190        console.error('Failed to retrieve current angles or angles are undefined.');
191        return;
192        }
193
194        // 获取旋转限位
195        const rotationLimits = mechanicManager.getRotationLimits(mechId);
196        if (!rotationLimits || rotationLimits.negativeYawMax === undefined || rotationLimits.positiveYawMax === undefined ||
197        rotationLimits.negativePitchMax === undefined || rotationLimits.positivePitchMax === undefined ||
198        rotationLimits.negativeRollMax === undefined || rotationLimits.positiveRollMax === undefined) {
199        console.error('Failed to retrieve rotation limits or limits are undefined.');
200        return;
201        }
202        console.log('Rotation limits:', rotationLimits);
203
204        // 定义目标角度并确保类型正确
205        const angles: mechanicManager.RotationAngles = {
206        yaw: Math.PI / 4, // 偏航角:45度
207        pitch: Math.PI / 6, // 俯仰角:30度
208        roll: 0            // 横滚角:0度
209        };
210
211        // 检查目标角度是否超出限位
212        if (
213        currentAngles.yaw + (angles.yaw ?? 0) > rotationLimits.negativeYawMax ||
214            currentAngles.yaw + (angles.yaw ?? 0) < rotationLimits.positiveYawMax ||
215            currentAngles.pitch + (angles.pitch ?? 0) > rotationLimits.negativePitchMax ||
216            currentAngles.pitch + (angles.pitch ?? 0) < rotationLimits.positivePitchMax ||
217            currentAngles.roll + (angles.roll ?? 0) > rotationLimits.negativeRollMax ||
218            currentAngles.roll + (angles.roll ?? 0) < rotationLimits.positiveRollMax
219        ) {
220        console.error('Target angles exceed rotation limits.');
221        return;
222        }
223
224        const duration = 2000; // 旋转持续时间:2秒
225
226        // 执行旋转
227        const result = await mechanicManager.rotate(mechId, angles, duration);
228        console.info(`Rotation Result: ${result}`);
229    } catch (err) {
230        console.error('Failed to rotate relative angle:', err);
231    }
232    }
233    ```
234
2353. 以指定速度持续转动。
236
237    ```ts
238    async function rotateBySpeed() {
239    try {
240        const mechId = savedMechanicIds[0]; // 假设使用第一个设备
241
242        // 获取速度控制最大持续时间
243        const maxTime = mechanicManager.getMaxRotationTime(mechId);
244        console.log('Maximum spin time:', maxTime);
245
246        // 获取最大旋转速度
247        const maxSpeed = mechanicManager.getMaxRotationSpeed(mechId);
248        if (!maxSpeed || maxSpeed.yawSpeed === undefined || maxSpeed.pitchSpeed === undefined || maxSpeed.rollSpeed === undefined) {
249        console.error('Failed to retrieve maximum rotation speed or speed values are undefined.');
250        return;
251        }
252        console.log('Maximum rotation speed:', maxSpeed);
253        // 定义旋转速度和持续时间
254        const speed : mechanicManager.RotationSpeed = {
255        yawSpeed: maxSpeed.yawSpeed / 2,    // 偏航速度:最大速度的一半
256        pitchSpeed: maxSpeed.pitchSpeed / 2, // 俯仰速度:最大速度的一半
257        rollSpeed: maxSpeed.rollSpeed / 2    // 横滚速度:最大速度的一半
258        };
259        const duration = Math.min(maxTime, 5000); // 持续时间:不超过最大持续时间,最多5秒
260
261        // 执行旋转
262        const result = await mechanicManager.rotateBySpeed(mechId, speed, duration);
263        console.info(`Rotation by speed result: ${result}`);
264    } catch (err) {
265        console.error('Failed to rotate by speed:', err);
266    }
267    }
268    ```
269
2704. 监听旋转轴状态变化。
271
272    ```ts
273    const rotationAxesCallback = (info: mechanicManager.RotationAxesStateChangeInfo) => {
274    console.log('Rotating Axes state change:', info);
275    const mechId = info.mechId;
276    const status = info.status;
277
278    console.log(`Device ${mechId} status update:`);
279    console.log(`- Yaw  axes enabled: ${status.yawEnabled}`);
280    console.log(`- Pitch axes enabled: ${status.pitchEnabled}`);
281    console.log(`- Roll axes enabled: ${status.rollEnabled}`);
282
283    if (status.yawLimited !== undefined) {
284        console.log(`- Yaw axis restriction state: ${status.yawLimited}`);
285    }
286    };
287
288    // 注册监听
289    mechanicManager.on('rotationAxesStatusChange', rotationAxesCallback);
290    ```
291
2925. 停止设备运动。
293
294    ```ts
295    async function stopDeviceMoving() {
296    try {
297        const mechId = savedMechanicIds[0];
298        await mechanicManager.stopMoving(mechId);
299        console.log('The device has stopped moving');
300    } catch (err) {
301        console.error('Failed to stop device movement:', err);
302    }
303    }
304    ```
305
306### 调试验证
307
308为了确保机械设备管理功能正常工作,请按照以下步骤进行调试验证:
309
310**建立连接**
311
3121. 确保机械体配件设备与开发设备通过蓝牙成功配对并建立连接。
3132. 将开发设备正确放置在机械体配件设备上。
314
315**功能验证步骤**
316
3171. **设备列表查询**:调用 `getAttachedMechDevices` 接口查询当前已连接的机械体配件设备列表,验证设备是否正确识别。
3182. **设备转动控制**:调用 `setCameraTrackingEnabled` 关闭跟踪功能,通过 `getCameraTrackingEnabled` 验证状态,调用 `rotate` 或 `rotateBySpeed` 控制设备转动。
319
320**验证结果说明**
321
322- 如果 `getAttachedMechDevices` 返回包含机械体配件设备信息的设备列表,表示设备识别正常。
323- 如果调用 `rotate` 或 `rotateBySpeed` 按预期开始转动,表示转动控制正常。
324