API(C++)
C++ 接口说明
fd_api 共享库 · 外设控制接口参考
PIMPL 封装 · namespace fd_robot一、概述
fd_api 提供机器人外设(升降、头部、腰部、手部)的 C++ 共享库 接口封装。 采用 PIMPL(Pointer to Implementation) 惯用法设计, 对外头文件不包含任何 ROS 头文件,使用者无需依赖 ROS 2 构建环境即可编译引用。
接口按职责划分为 Control(控制) 与 State(状态) 两大模块, 所有类型定义位于 namespace fd_robot 命名空间下。
设计原则:PIMPL 实现将实现细节完全隐藏,保持 ABI 稳定; 对外接口仅暴露纯 C++ 类型和枚举,无 ROS 依赖泄漏。
二、类型定义
所有枚举和回调类型定义在 namespace fd_robot 下。
2.1 枚举类型
| 类型 | 枚举值 | 说明 |
|---|---|---|
enum class HeadType |
kLower = 0kUpper = 1 |
头部关节:kLower 为水平旋转(yaw),kUpper 为俯仰(pitch) |
enum class HandType |
kLeft = 0kRight = 1kBoth = 2 |
手部选择:左手 / 右手 / 双手 |
enum class HandBackend |
kRohand = 0kInspire = 1kBoth = 2 |
手部驱动后端:RoHand / Inspire / 双后端兼容 |
2.2 回调类型
| 类型别名 | 定义 | 说明 |
|---|---|---|
SubscriptionId |
uint64_t |
异步订阅的唯一标识符,用于取消订阅 |
LiftPosCallback |
std::function<void(double)> |
升降位置回调,参数为位置值(mm) |
HeadPosCallback |
std::function<void(double)> |
头部位置回调,参数为角度值(°) |
WaistDegCallback |
std::function<void(double)> |
腰部位置回调,参数为角度值(°) |
HandPosCallback |
std::function<void(double)> |
手部位置回调,参数为位置值 |
三、Options 配置结构体
3.1 Control::Options
用于 Control::Init() 的初始化配置参数。
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
node_name |
std::string |
"fd_api_control" |
ROS 2 节点名称 |
hand_backend |
HandBackend |
kInspire |
手部驱动后端 |
hand_type |
HandType |
kBoth |
手部选择 |
waist_servo_id |
int |
3 |
腰部舵机 ID |
inspire_gripper_id |
int |
1 |
Inspire 手爪 ID |
3.2 State::Options
用于 State::Init() 的初始化配置参数。
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
node_name |
std::string |
"fd_api_state" |
ROS 2 节点名称 |
callback_thread_count |
int |
2 |
回调线程池数量 |
waist_servo_id |
int |
3 |
腰部舵机 ID |
inspire_gripper_id |
int |
1 |
Inspire 手爪 ID |
四、Control 控制接口
fd_robot::Control 提供机器人外设的运动控制接口,所有方法为阻塞式调用。
4.1 初始化
| 方法签名 | 说明 |
|---|---|
bool Init(const Options& opts) |
初始化 Control 实例并连接 ROS 2 节点。 返回 true 表示初始化成功。必须在其他方法前调用。 |
使用示例
#include "fd_api/control.h"
#include "fd_api/state.h"
#include "fd_api/types.h"
// Control 初始化
fd_robot::Control ctrl;
fd_robot::Control::Options ctrl_opts;
ctrl_opts.node_name = "my_control";
ctrl_opts.hand_backend = fd_robot::HandBackend::kInspire;
ctrl_opts.hand_type = fd_robot::HandType::kBoth;
ctrl_opts.waist_servo_id = 3;
ctrl_opts.inspire_gripper_id = 1;
ctrl.Init(ctrl_opts);
4.2 升降
| 方法签名 | 说明 |
|---|---|
void lift_up(double spd) |
升降上升(速度模式) |
void lift_down(double spd) |
升降下降(速度模式) |
void lift_set_pos(double spd, double pos_mm) |
升降移动到指定位置(位置模式) |
void lift_stop() |
停止升降运动 |
速度模式须周期发送:
lift_up / lift_down 为速度模式, 驱动在约 1 秒内未收到新速度命令会自动停止,上位机须周期性调用(建议间隔 < 500ms)。使用示例
// 升降速度控制
ctrl.lift_up(0.05f); // 上升
ctrl.lift_down(0.05f); // 下降
ctrl.lift_stop(); // 停止
// 升降位置控制(速度 m/s, 位置 mm)
ctrl.lift_set_pos(0.05f, 200.0f);
4.3 头部
| 方法签名 | 说明 |
|---|---|
void head_set_pos(HeadType type, double pos_deg) |
头部移动到指定角度(位置模式) |
void head_stop(HeadType type) |
停止头部运动 |
角度限幅范围
| 关节 | 最小值 | 最大值 |
|---|---|---|
HeadType::kLower (水平旋转 / yaw) |
-45° | +45° |
HeadType::kUpper (俯仰 / pitch) |
-15° | +25° |
输入超限值会被自动钳位至有效范围内。
使用示例
// 头部角度控制
ctrl.head_set_pos(fd_robot::HeadType::kLower, 30.0f); // 下头 30°
ctrl.head_set_pos(fd_robot::HeadType::kUpper, 10.0f); // 上头 10°
ctrl.head_stop(fd_robot::HeadType::kLower); // 停止下头
4.4 腰部
| 方法签名 | 说明 |
|---|---|
void waist_front(double spd, double acc, double dec) |
腰部前倾(速度模式) |
void waist_back(double spd, double acc, double dec) |
腰部后仰(速度模式) |
void waist_set_pos(double spd, double acc, double dec, double pos_deg) |
腰部移动到指定角度(位置模式) |
void waist_stop() |
停止腰部运动 |
腰部角度范围:位置控制范围为 0°~35°。
使用示例
// 腰部速度模式
ctrl.waist_front(720, 100, 100); // 前倾
ctrl.waist_back(720, 100, 100); // 后仰
// 腰部位置模式 (0°~35°)
ctrl.waist_set_pos(720, 100, 100, 15.0f);
ctrl.waist_stop(); // 停止
4.5 手部
| 方法签名 | 说明 |
|---|---|
void hand_move(HandType type, double value) |
手部运动到指定位置 |
void hand_stop(HandType type) |
停止手部运动 |
使用示例
// RoHand 手部控制
std::vector<float> hand_vals = {0.0f, 0.5f, 0.3f, 0.1f, 0.0f, 0.0f};
ctrl.hand_move(fd_robot::HandType::kLeft, hand_vals);
// Inspire 夹爪
std::vector<float> gripper_val = {500.0f};
ctrl.hand_move(fd_robot::HandType::kRight, gripper_val);
ctrl.hand_stop(fd_robot::HandType::kLeft);
五、State 状态接口
fd_robot::State 提供机器人外设的状态读取与异步订阅接口。
5.1 初始化
| 方法签名 | 说明 |
|---|---|
bool Init(const Options& opts) |
初始化 State 实例并连接 ROS 2 节点。 返回 true 表示初始化成功。必须在其他方法前调用。 |
使用示例
// State 初始化
fd_robot::State state;
fd_robot::State::Options state_opts;
state_opts.node_name = "my_state";
state_opts.callback_thread_count = 2;
state_opts.waist_servo_id = 3;
state_opts.inspire_gripper_id = 1;
state.Init(state_opts);
5.2 同步读取
同步读取接口从内部缓存获取最新数据,返回 bool 表示是否已成功收到过数据。
| 方法签名 | 说明 |
|---|---|
bool lift_get_current_pos(double& pos) |
获取升降当前位置(mm) |
bool head_get_current_pos(HeadType type, double& pos) |
获取头部当前位置(°) |
bool waist_get_current_pos(double& pos) |
获取腰部当前位置(°) |
bool hand_get_current_pos(HandType type, double& pos) |
获取手部当前位置 |
使用示例
// 同步读取状态
float lift_pos = 0.0f;
if (state.lift_get_current_pos(lift_pos)) {
printf("当前升降位置: %.1f mm\n", lift_pos);
}
float head_lower = 0.0f;
state.head_get_current_pos(fd_robot::HeadType::kLower, head_lower);
printf("下头角度: %.1f deg\n", head_lower);
float waist_angle = 0.0f;
state.waist_get_current_pos(waist_angle);
printf("腰部角度: %.1f deg\n", waist_angle);
std::vector<float> hand_pos;
state.hand_get_current_pos(fd_robot::HandType::kLeft, hand_pos);
5.3 异步订阅
异步订阅接口注册回调函数,有新数据时由内部线程池异步调用。返回 SubscriptionId 用于取消订阅。
| 方法签名 | 说明 |
|---|---|
SubscriptionId lift_sub_current_pos(LiftPosCallback cb) |
订阅升降位置更新 |
SubscriptionId head_sub_current_pos(HeadPosCallback cb) |
订阅头部位置更新 |
SubscriptionId waist_sub_current_pos(WaistDegCallback cb) |
订阅腰部位置更新 |
SubscriptionId hand_sub_current_pos(HandType type, HandPosCallback cb) |
订阅手部位置更新 |
使用示例
// 异步订阅升降位置
fd_robot::SubscriptionId sid = state.lift_sub_current_pos(
[](float mm) {
printf("升降位置更新: %.1f mm\n", mm);
});
// 取消订阅
state.unsubscribe(sid);
5.4 取消订阅
| 方法签名 | 说明 |
|---|---|
void unsubscribe(SubscriptionId id) |
取消指定的订阅 |
六、C++ 示例代码
以下示例展示 Control 和 State 的完整用法,包含所有外设的控制与状态读取操作:
#include <chrono>
#include <iostream>
#include <thread>
#include <vector>
#include "fd_api/control.h"
#include "fd_api/state.h"
#include "fd_api/types.h"
using namespace fd_robot;
int main() {
// ── Control 初始化 ──
Control::Options ctrl_opts;
ctrl_opts.node_name = "my_control";
ctrl_opts.hand_backend = HandBackend::kInspire;
ctrl_opts.hand_type = HandType::kBoth;
ctrl_opts.waist_servo_id = 3;
ctrl_opts.inspire_gripper_id = 1;
Control ctrl;
if (!ctrl.Init(ctrl_opts)) {
std::cerr << "Control init failed" << std::endl;
return -1;
}
// ── 升降控制 ──
ctrl.lift_up(0.05f); // 上升(速度模式)
std::this_thread::sleep_for(std::chrono::milliseconds(300));
ctrl.lift_stop();
ctrl.lift_set_pos(0.05f, 200.0f); // 升降移动到 200 mm(位置模式)
// ── 头部控制 ──
ctrl.head_set_pos(HeadType::kLower, 30.0f); // 下头 30°
ctrl.head_set_pos(HeadType::kUpper, 10.0f); // 上头 10°
// ── 腰部控制 ──
ctrl.waist_front(720, 100, 100); // 前倾(速度模式)
std::this_thread::sleep_for(std::chrono::milliseconds(500));
ctrl.waist_stop();
ctrl.waist_set_pos(720, 100, 100, 15.0f); // 腰部到 15°(位置模式)
// ── 手部控制 ──
std::vector<float> hand_vals = {0.0f, 0.5f, 0.3f, 0.1f, 0.0f, 0.0f};
ctrl.hand_move(HandType::kLeft, hand_vals);
ctrl.hand_stop(HandType::kLeft);
// ── State 初始化 ──
State::Options state_opts;
state_opts.node_name = "my_state";
state_opts.callback_thread_count = 2;
state_opts.waist_servo_id = 3;
state_opts.inspire_gripper_id = 1;
State state;
if (!state.Init(state_opts)) {
std::cerr << "State init failed" << std::endl;
return -1;
}
// ── 同步读取 ──
double pos = 0.0;
if (state.lift_get_current_pos(pos)) {
std::cout << "Current lift pos: " << pos << " mm" << std::endl;
}
double head_lower = 0.0;
state.head_get_current_pos(HeadType::kLower, head_lower);
std::cout << "下头角度: " << head_lower << " deg" << std::endl;
double waist_angle = 0.0;
state.waist_get_current_pos(waist_angle);
std::cout << "腰部角度: " << waist_angle << " deg" << std::endl;
// ── 异步订阅 ──
auto sub_id = state.lift_sub_current_pos(
[](double p) {
std::cout << "Lift pos updated: " << p << " mm" << std::endl;
});
// ── 停止操作 ──
ctrl.lift_stop();
ctrl.head_stop(HeadType::kLower);
ctrl.head_stop(HeadType::kUpper);
ctrl.waist_stop();
// ── 取消订阅 ──
state.unsubscribe(sub_id);
return 0;
}
七、测试工具
项目提供交互式测试节点,可用于验证接口功能:
# 编译
colcon build --packages-select fd_api
# 运行交互测试
ros2 run fd_api api_test_node
提示:运行前请确保 ROS 2 环境已加载(
source install/setup.bash), 且机器人外设节点已启动。交互测试提供菜单操作,可分别测试各外设的控制与状态接口。八、注意事项
速度模式须周期发送:升降速度模式(
lift_up / lift_down)下, 驱动在约 1 秒 内未收到新速度命令会自动停止, 上位机须 周期性调用(建议间隔 < 500ms),单次调用不足以维持连续升降。PIMPL 线程安全:
Control 和 State 实现内部使用互斥锁保证线程安全。 Init() 方法必须在所有其他方法之前完成调用,多线程环境下请确保初始化顺序。头部角度限幅:
HeadType::kLower (yaw) 限幅 -45°~+45°, HeadType::kUpper (pitch) 限幅 -15°~+25°。输入超限值会被自动钳位。腰部角度范围:位置控制范围为 0°~35°。
回调线程安全:状态订阅回调在线程池中执行,线程数量由
State::Options::callback_thread_count 配置(默认 2)。 请确保回调函数内部无竞态条件,避免在回调中执行阻塞操作。