头部关节

1.head_set_pos - 头部角度控制

方法: ctrl.head_set_pos(type, pos_deg)

C++ 签名: bool head_set_pos(HeadType type, float pos_deg);

参数:

  • type:头部类型,fd_robot::HeadType 枚举
    • HeadType::kLower:下头(yaw),水平旋转
    • HeadType::kUpper:上头(pitch),俯仰
  • pos_deg:目标角度,float 类型,单位:度 (°)。正值 = 前/上,负值 = 后/下。内部自动限幅:
    • HeadType::kLower (yaw):-45° ~ +45°
    • HeadType::kUpper (pitch):-15° ~ +25°

返回值:

  • bool:操作结果
    • true:指令发送成功
    • false:指令发送失败

使用示例:

C++
#include "fd_api/control.h"
#include <cstdio>

int main() {
    fd_robot::Control ctrl;
    fd_robot::Control::Options opts;
    opts.node_name = "fd_api_control";
    if (!ctrl.Init(opts)) {
        return 1;
    }

    // 下头(yaw)转到 30°
    bool ok = ctrl.head_set_pos(fd_robot::HeadType::kLower, 30.0f);
    if (ok) {
        printf("下头角度指令发送成功\n");
    } else {
        printf("下头角度指令发送失败\n");
    }

    // 上头(pitch)转到 10°
    ctrl.head_set_pos(fd_robot::HeadType::kUpper, 10.0f);

    // 下头转到 -20°(向后)
    ctrl.head_set_pos(fd_robot::HeadType::kLower, -20.0f);
    return 0;
}

注意: 限幅范围由机型 robot_profile 的 head_upper_range / head_lower_range 配置决定,上表为默认机型范围;输入超限值会被自动钳位。

2.head_stop - 头部停止

方法: ctrl.head_stop(type)

C++ 签名: bool head_stop(HeadType type);

参数:

  • type:头部类型,fd_robot::HeadType 枚举
    • HeadType::kLower:停止下头(yaw)
    • HeadType::kUpper:停止上头(pitch)

返回值:

  • bool:操作结果
    • true:指令发送成功
    • false:指令发送失败

使用示例:

C++
#include "fd_api/control.h"
#include <cstdio>

int main() {
    fd_robot::Control ctrl;
    fd_robot::Control::Options opts;
    opts.node_name = "fd_api_control";
    if (!ctrl.Init(opts)) {
        return 1;
    }

    // 停止下头运动
    ctrl.head_stop(fd_robot::HeadType::kLower);

    // 停止上头运动
    ctrl.head_stop(fd_robot::HeadType::kUpper);
    return 0;
}

3.head_get_current_pos - 获取头部当前位置(同步读取)

方法: state.head_get_current_pos(type, angle_deg)

C++ 签名: bool head_get_current_pos(HeadType type, float &angle_deg) const;

参数:

  • type:头部类型,fd_robot::HeadType 枚举
    • HeadType::kLower:读取下头(yaw)当前位置
    • HeadType::kUpper:读取上头(pitch)当前位置
  • angle_deg:出参,float & 类型,返回当前头部角度,单位:度 (°)

返回值:

  • bool:表示是否已有有效缓存数据
    • true:已有数据,angle_deg 有效
    • false:尚无数据,angle_deg 不可信

使用示例:

C++
#include "fd_api/state.h"
#include <cstdio>

int main() {
    fd_robot::State state;
    if (!state.Init()) {
        return 1;
    }

    // 读取下头(yaw)当前位置
    float yaw = 0.0f;
    if (state.head_get_current_pos(fd_robot::HeadType::kLower, yaw)) {
        printf("下头(yaw)角度:%.1f°\n", yaw);
    }

    // 读取上头(pitch)当前位置
    float pitch = 0.0f;
    if (state.head_get_current_pos(fd_robot::HeadType::kUpper, pitch)) {
        printf("上头(pitch)角度:%.1f°\n", pitch);
    }
    return 0;
}

注意: 返回 false 表示该轴尚无有效缓存数据(对应 Python 版的 None),此时出参不可信,建议先订阅或等待数据到达后再读取。

4.head_sub_current_pos - 订阅头部位置(异步回调)

方法: state.head_sub_current_pos(cb)

C++ 签名: SubscriptionId head_sub_current_pos(HeadPosCallback cb);  // cb: void(HeadType, float deg)

参数:

  • cb:回调函数,std::function<void(fd_robot::HeadType, float)> 类型
    • HeadType:标识是下头还是上头
    • float:角度值,单位:度 (°)

返回值:

  • SubscriptionId:订阅ID,类型为 uint64_t。可用于后续取消订阅;空回调返回 0(失败)

使用示例:

C++
#include "fd_api/state.h"
#include <cstdio>

int main() {
    fd_robot::State state;
    if (!state.Init()) {
        return 1;
    }

    // 订阅头部位置(同时接收下头和上头的更新)
    fd_robot::SubscriptionId sid = state.head_sub_current_pos(
        [](fd_robot::HeadType type, float deg) {
            const char* name =
                (type == fd_robot::HeadType::kLower) ? "下头" : "上头";
            printf("%s角度更新:%.1f°\n", name, deg);
        });
    if (sid != 0) {
        printf("订阅成功,订阅ID:%llu\n", sid);
    }

    // 无需接收时取消订阅
    state.unsubscribe(sid);
    printf("已取消头部位置订阅\n");
    return 0;
}

建议:

  • 订阅的回调在线程池中执行,注意线程安全
  • 无需接收位置更新时及时取消订阅,避免不必要的回调
  • 可与 head_get_current_pos 同步读取配合使用