集成与上层应用
UDP 通信架构
Section titled “UDP 通信架构”SDK 底层通信基于自封装的 UDP Socket 层:
graph TB A["Gamepad<KeysType>"] --> B["UdpReceiver"] B --> C["Linux Socket API"]UdpReceiver:封装 Socket 创建、端口绑定和数据接收Gamepad<KeysType>:在独立线程中循环调用UdpReceiver::ReceiveData(),将原始数据交给子类的UpdateData()解析
数据接收流程
Section titled “数据接收流程”graph TB A["UdpReceiver 阻塞等待 UDP 数据"] --> B["收到原始字节流"] B --> C["Gamepad 调用子类 UpdateData"] C --> D{"DataIsValid 三级校验"} D -->|"通过"| E["解析按键和摇杆数据"] E --> F["触发 updateCallback_"] D -->|"失败"| ASDK 使用独立的数据接收线程:
StartDataThread()创建并detach一个后台线程- 线程内循环调用
ReceiveData()(阻塞),收到数据后通过mutex_保护按键数据的读写 GetKeys()通过同一mutex_保证线程安全StopDataThread()设置stop_thread_原子标志,线程在下一次循环退出
集成到上层应用
Section titled “集成到上层应用”在项目的 CMakeLists.txt 中引用 SDK:
# 指定 gamepad SDK 路径set(GAMEPAD_DIR "/path/to/gamepad")
# 引入头文件include_directories(${GAMEPAD_DIR}/include)
# 链接静态库link_directories(${GAMEPAD_DIR}/build)target_link_libraries(your_target gamepad_receiver)代码集成示例
Section titled “代码集成示例”#include "retroid_gamepad.h"#include "gamepad_keys.h"
// 创建手柄实例RetroidGamepad gamepad(12121);gamepad.StartDataThread();
// 方式一:回调方式获取数据gamepad.SetUpdateCallback([](uint32_t count) { // 数据已更新});
// 方式二:轮询方式获取数据while (running) { RetroidKeys& keys = gamepad.GetKeys(); float vx = keys.left_axis_y; // 前进速度 float vy = keys.left_axis_x; // 横向速度 float omega = keys.right_axis_x; // 旋转速度
if (keys.Y) { // Y 键按下 → 站立 } if (keys.A) { // A 键按下 → RL 控制 } if (keys.left_axis_button && keys.right_axis_button) { // 双摇杆按下 → 紧急阻尼 }
std::this_thread::sleep_for(std::chrono::milliseconds(5));}与 lite3_transfer 集成
Section titled “与 lite3_transfer 集成”在 lite3_transfer 中,RetroidGamepadPublisher 封装了 Gamepad SDK 并定期将手柄数据发布到 ROS2 话题 /GAMEPAD_DATA:
auto gamepad_ptr = std::make_shared<RetroidGamepad>(12121);gamepad_ptr->StartDataThread();
// 周期读取并发布RetroidKeys rt_keys = gamepad_ptr->GetKeys();drdds::msg::GamepadData msg;msg.left_axis_x = rt_keys.left_axis_x;msg.left_axis_y = rt_keys.left_axis_y;msg.right_axis_x = rt_keys.right_axis_x;msg.right_axis_y = rt_keys.right_axis_y;msg.buttons = rt_keys.value;安全注意事项
Section titled “安全注意事项”-
确保网络隔离:手柄 App 通过 UDP 广播数据,确保开发网络与其他网络隔离,避免数据被干扰或截获。
-
防火墙配置:编译和运行前确保 UDP 端口已放行,否则无法接收手柄数据。
-
心跳检测:上层应用应实现手柄心跳检测机制,当长时间未收到手柄数据时自动进入安全模式(如阻尼状态),防止失控。
-
端口冲突:确保端口
12121未被其他程序占用,可通过以下命令检查:
sudo lsof -i:12121