Files
OmniSocketGo/ros-control-py/README.md

258 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ROS2 Teleop over OmniSocket UDP/KCP
`ros-control-py/udp_teleop_bridge` 现在把 teleop 控制流统一接到 OmniSocket peer 传输上。
- `transport:=udp` 表示 OmniSocket UDP`udpserver/udppeer` 的消息协议传输
- `transport:=kcp` 表示 OmniSocket KCP`kcpserver/kcppeer` 的消息协议传输
- 不再使用原来的裸 `socket.sendto()/recvfrom()` UDP 路径
机器人最终接收的话题保持不变:
- topic: `/hric/robot/cmd_vel`
- type: `geometry_msgs/msg/TwistStamped`
- frame_id: `pelvis`
控制负载也保持不变:
- fixed payload: 24-byte little-endian `<6f>`
- order: `lx, ly, lz, ax, ay, az`
## 目录
- `udp_teleop_bridge/udp_teleop_bridge/cmd_vel_udp_sender.py`: 订阅 `TwistStamped`,经 OmniSocket 发送 24 字节控制包
- `udp_teleop_bridge/udp_teleop_bridge/udp_cmd_vel_receiver.py`: 从 OmniSocket 接收控制包,补时间戳并发布到机器人 ROS2 topic
- `udp_teleop_bridge/udp_teleop_bridge/omni_transport.py`: 统一封装 OmniSocket UDP/KCP session
- `udp_teleop_bridge/config/xbox_twist_joy.yaml`: Xbox 手柄映射
- `udp_teleop_bridge/launch/*.launch.py`: Linux 启动入口
## Linux 构建
先安装 ROS 2 官方 teleop 依赖:
```bash
sudo apt install ros-${ROS_DISTRO}-joy ros-${ROS_DISTRO}-teleop-twist-joy ros-${ROS_DISTRO}-teleop-twist-keyboard
```
再构建并安装 OmniSocket Python 扩展:
```bash
make python-ext
make python-install
```
最后构建 ROS 包:
```bash
colcon build --packages-select udp_teleop_bridge
source install/setup.bash
```
如果 `omnisocket` 没有安装到当前 ROS Python 环境sender/receiver 会直接报错退出。
## 先验证机器人控制语义
在机器人本机先直接低速发布 `/hric/robot/cmd_vel`,确认 `linear.x``linear.y``angular.z` 的物理方向符合预期:
```bash
ros2 topic pub /hric/robot/cmd_vel geometry_msgs/msg/TwistStamped \
"{header: {frame_id: pelvis}, twist: {linear: {x: 0.10, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.0}}}" \
-r 20
```
```bash
ros2 topic pub /hric/robot/cmd_vel geometry_msgs/msg/TwistStamped \
"{header: {frame_id: pelvis}, twist: {linear: {x: 0.0, y: 0.10, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.0}}}" \
-r 20
```
```bash
ros2 topic pub /hric/robot/cmd_vel geometry_msgs/msg/TwistStamped \
"{header: {frame_id: pelvis}, twist: {linear: {x: 0.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.30}}}" \
-r 20
```
停止:
```bash
ros2 topic pub --once /hric/robot/cmd_vel geometry_msgs/msg/TwistStamped \
"{header: {frame_id: pelvis}, twist: {linear: {x: 0.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.0}}}"
```
## 启动 OmniSocket Hub
OmniSocket UDP:
```bash
./bin/udpserver -listen :9001
```
OmniSocket KCP:
```bash
./bin/kcpserver -listen :9002
```
`server_addr` 不传时,节点会按 `transport` 自动选择默认值:
- `udp` -> `127.0.0.1:9001`
- `kcp` -> `127.0.0.1:9002`
`relay_via` 只在 `transport:=kcp` 时生效。
## 机器人端运行
UDP:
```bash
ros2 launch udp_teleop_bridge robot_udp_receiver.launch.py \
transport:=udp \
server_addr:=127.0.0.1:9001 \
peer_id:=ros-bridge-ctrl \
output_topic:=/hric/robot/cmd_vel \
frame_id:=pelvis \
watchdog_timeout:=0.5
```
KCP:
```bash
ros2 launch udp_teleop_bridge robot_udp_receiver.launch.py \
transport:=kcp \
server_addr:=127.0.0.1:9002 \
peer_id:=ros-bridge-ctrl \
output_topic:=/hric/robot/cmd_vel \
frame_id:=pelvis \
watchdog_timeout:=0.5
```
如果只允许某个 sender 控制,可以加:
```bash
expected_sender:=ros-keyboard-ctrl
```
Local daemon handoff via Unix datagram:
```bash
ros2 launch udp_teleop_bridge robot_udp_receiver.launch.py \
transport:=unix_dgram \
local_socket_path:=/tmp/omnisocket-b-side-cmd.sock \
output_topic:=/hric/robot/cmd_vel \
frame_id:=pelvis \
watchdog_timeout:=0.5
```
## 控制端键盘运行
终端 A启动 sender:
```bash
ros2 launch udp_teleop_bridge keyboard_sender.launch.py \
transport:=udp \
server_addr:=127.0.0.1:9001 \
peer_id:=ros-keyboard-ctrl \
target_peer:=ros-bridge-ctrl
```
如果走 KCP:
```bash
ros2 launch udp_teleop_bridge keyboard_sender.launch.py \
transport:=kcp \
server_addr:=127.0.0.1:9002 \
peer_id:=ros-keyboard-ctrl \
target_peer:=ros-bridge-ctrl
```
终端 B启动官方键盘 teleop:
```bash
ros2 run teleop_twist_keyboard teleop_twist_keyboard --ros-args \
--remap cmd_vel:=/teleop/cmd_vel \
-p stamped:=true \
-p frame_id:=pelvis \
-p speed:=0.20 \
-p turn:=0.60
```
键盘默认键位(`teleop_twist_keyboard`,建议使用 US 键盘布局):
- `i`: 前进(`linear.x > 0`
- `,`: 后退(`linear.x < 0`
- `j`: 左转(`angular.z > 0`
- `l`: 右转(`angular.z < 0`
- `Shift + J`: 左平移(`linear.y > 0`
- `Shift + L`: 右平移(`linear.y < 0`
- `u` / `o` / `m` / `.`: 组合前进或后退加转向
- `k` 或其他未映射按键: 停止
- `q` / `z`: 整体速度增加 / 降低 10%
- `w` / `x`: 仅线速度增加 / 降低 10%
- `e` / `c`: 仅角速度增加 / 降低 10%
- `Ctrl-C`: 退出键盘 teleop
## 控制端 Xbox 手柄运行
UDP:
```bash
ros2 launch udp_teleop_bridge xbox_to_udp.launch.py \
transport:=udp \
server_addr:=127.0.0.1:9001 \
peer_id:=ros-gamepad-ctrl \
target_peer:=ros-bridge-ctrl \
joy_dev:=/dev/input/js0 \
frame_id:=pelvis
```
KCP:
```bash
ros2 launch udp_teleop_bridge xbox_to_udp.launch.py \
transport:=kcp \
server_addr:=127.0.0.1:9002 \
peer_id:=ros-gamepad-ctrl \
target_peer:=ros-bridge-ctrl \
joy_dev:=/dev/input/js0 \
frame_id:=pelvis
```
当前默认手柄映射:
- 左摇杆上下 -> `linear.x`
- 左摇杆左右 -> `linear.y`
- 右摇杆左右 -> `angular.z`
- `RB` 按住才允许运动
- `LB` 为 turbo
手柄实际操控含义(基于 `config/xbox_twist_joy.yaml` 的 Xbox 默认映射):
- 左摇杆向前 / 向后: 前进 / 后退
- 左摇杆向左 / 向右: 左平移 / 右平移
- 右摇杆向左 / 向右: 左转 / 右转
- 按住 `RB`: 以常速启用运动输出
- 同时按住 `LB` + `RB`: 启用 turbo更高的线速度和角速度
- 松开 `RB` 或将摇杆回中: 输出回到零速
## 数据流
键盘链路:
```text
teleop_twist_keyboard -> /teleop/cmd_vel (TwistStamped) -> cmd_vel_udp_sender -> OmniSocket UDP/KCP -> udp_cmd_vel_receiver -> /hric/robot/cmd_vel
```
手柄链路:
```text
joy_node -> teleop_twist_joy -> /teleop/cmd_vel (TwistStamped) -> cmd_vel_udp_sender -> OmniSocket UDP/KCP -> udp_cmd_vel_receiver -> /hric/robot/cmd_vel
```
## 安全行为
- sender 默认按 20 Hz 重发最新命令
- sender 输入超时后会改发零速
- sender 退出时会主动发送数个零速控制包
- receiver 超时后会在 ROS 主线程发布零速 stop
- receiver 只接受 `MSG_TYPE_BINARY` 且长度为 24 字节的负载
- 非预期 sender、非 binary 消息、错误长度消息都会被丢弃并记录日志