update README.md

This commit is contained in:
2026-06-20 19:49:23 +08:00
parent 74396f48a0
commit 3ca49bd852

291
README.md
View File

@@ -2,7 +2,7 @@
> 本仓库为 **[中国机器人及人工智能大赛](https://www.caairobot.com)**CRAIC**机器人任务挑战赛(小型桌面级)** 参赛代码。
ESP32-S3 双核摄像头 + ROS 2 机械臂控制 + 视觉抓取的一体化机器人系统。
ESP32-S3 双核摄像头 + ROS 2 机械臂控制 + 视觉抓取 + 激光 SLAM 定位导航的一体化机器人系统。
## 赛事信息
@@ -19,24 +19,6 @@ ESP32-S3 双核摄像头 + ROS 2 机械臂控制 + 视觉抓取的一体化机
| 参赛赛项 | 机器人任务挑战赛(小型桌面级) |
| 官方网站 | [www.caairobot.com](https://www.caairobot.com) |
## 项目结构
```
craic/
├── jxbeye/ # ESP32-S3 固件 (PlatformIO)
│ ├── src/main.cpp # 双核摄像头推流 + UDP 控制
│ └── platformio.ini # ESP32-S3-WROOM-1-N16R8 配置
├── ros2/ # ROS 2 控制系统
│ ├── src/arm_control_msgs/ # 消息和服务定义
│ └── src/udp_teleop/ # 机械臂控制和视觉抓取节点
├── tools/ # 独立工具脚本
│ ├── udp_control.py # 命令行机械臂控制(带逆运动学)
│ ├── camera_to_base.py # 相机坐标到基坐标变换
│ └── camera_capture.py # MJPEG 流采集
└── docs/ # 技术文档
└── arm.md # 机械臂运动学推导
```
## 硬件
| 组件 | 型号 |
@@ -44,34 +26,100 @@ craic/
| 主控 | ESP32-S3-WROOM-1-N16R8 (16MB Flash, 8MB PSRAM) |
| 摄像头 | OV2640 (XGA 1024×768, JPEG) |
| 机械臂 | 6-DOF飞特 SCS/STS 串行舵机 |
| 激光雷达 | YDLiDAR TminiPro (360°, 10Hz) |
| 底盘 | 麦克纳姆轮底盘LZUCAR 底盘 MCU串口里程计 |
| 激光 | 激光模块LASERON / LASEROFF |
## 项目结构
```
craic/
├── jxbeye/ # ESP32-S3 固件 (PlatformIO)
│ ├── src/main.cpp # 双核Core 0 摄像头采集Core 1 WiFi推流 + UDP控制
│ ├── platformio.ini # 开发板与 PSRAM 配置
│ └── lib/FTServo/ # 飞特串行舵机库
├── ros2/ # ROS 2 控制系统
│ ├── build.sh # 一键编译脚本
│ ├── src/arm_control_msgs/ # 机械臂消息与服务定义 (ament_cmake)
│ │ ├── msg/ # JointState, TCPPose
│ │ └── srv/ # MoveJoints, MovePose, GetPose, SetGripper
│ ├── src/udp_teleop/ # UDP 遥控与机械臂控制 (ament_python)
│ │ ├── udp_teleop/ # arm_control, vision_grasp, keyboard_control, box_detection_grasp
│ │ ├── launch/ # vision_grasp.launch.py统一启动
│ │ ├── config/ # arm / vision / keyboard / box_detection 参数
│ │ └── models/ # YOLO 模型权重 (box_detection.pt)
│ ├── src/craic_localization/ # 定位与导航 (ament_python)
│ │ ├── launch/ # mapping / localization / lidar / bringup
│ │ ├── config/ # amcl / gmapping / lidar 参数
│ │ └── rviz/ # 定位专用 RViz 配置
│ ├── src/rf2o_laser_odometry/ # 激光里程计 (ament_cmake, C++14)
│ └── src/ydlidar_ros2_driver/ # YDLiDAR 驱动 (ament_cmake)
├── tools/ # 独立命令行工具(不依赖 ROS
│ ├── udp_control.py # 机械臂控制(逆运动学 + 插值)
│ ├── camera_to_base.py # 相机→基座坐标系变换
│ ├── camera_capture.py # MJPEG 流帧采集
│ ├── udp_server.py # UDP 回显调试服务器
│ └── README.md # 工具详细文档
├── docs/ # 技术文档
│ ├── arm.md # 机械臂运动学推导
│ ├── localization.md # 定位系统完整文档
│ └── box_detection_grasp.md # 方框检测与自动抓取
└── dataset/ # 竞赛训练数据(黑方块图像 + 标定)
```
## 核心功能
### 1. ESP32-S3 固件 (`jxbeye/`)
- **双核架构**Core 0 采集Core 1 推流
- **MJPEG 推流**`http://<IP>` 实时查看
- **UDP 控制**:端口 8888非阻塞异步处理
- **WiFi 配置**:串口发送 `WIFI:SSID:PASSWORD` 配置
- **双核架构**Core 0 采集 OV2640 JPEGCore 1 WiFi 推流 + 异步 UDP 命令接收
- **MJPEG 推流**`http://<IP>` 实时查看`/stream` 端点供 OpenCV/YOLO 消费
- **UDP 控制**:端口 8888非阻塞中断回调处理底盘 + 机械臂 + 激光指令
- **WiFi 配置**首次启动创建热点 `ESP32-S3-Camera`(密码 `12345678`串口发送 `WIFI:SSID:PASSWORD` 切换 Station 模式
### 2. ROS 2 机械臂控制 (`ros2/`)
### 2. 机械臂控制与视觉抓取 (`ros2/src/udp_teleop/`)
**arm_control 节点**
- 关节空间和笛卡尔空间运动控制
- 完整逆运动学正运动学
- 服务接口:`move_joints`, `move_pose`, `get_pose`, `set_gripper`
- 状态发布10Hz
| 节点 | 功能 |
|------|------|
| `arm_control` | 完整逆运动学/正运动学,关节空间 + 笛卡尔空间运动4 个 ROS 服务,状态发布 (10Hz),自动归零,动态 J5/z4 适配 |
| `vision_grasp` | 相机坐标→基坐标变换,自动抓取/释放流程(松开→移动→夹取→回收),多线程服务调用 |
| `box_detection_grasp` | YOLO 实时方框检测MJPEG 流),单目深度估计,自动/手动模式,检测到即触发抓取 |
| `keyboard_control` | 键盘 UDP 遥控(底盘 WASD/QE + 机械臂 ↑↓←→ + 关节选择 2-63 种输入后端 |
**vision_grasp 节点**
- 相机坐标到基坐标系自动转换
- 自动抓取:释放 → 移动 → 抓取 → 回收
- 自动释放:移动 → 释放 → 回收
**机械臂服务接口**
```bash
ros2 service call /arm_control/move_pose arm_control_msgs/srv/MovePose \
"{x: 200.0, y: 100.0, z: -100.0, phi: 45.0, duration: 2.0}"
ros2 service call /arm_control/get_pose arm_control_msgs/srv/GetPose
ros2 service call /arm_control/set_gripper arm_control_msgs/srv/SetGripper "{grip: true}"
```
### 3. 工具脚本 (`tools/`)
### 3. 激光 SLAM 定位与导航 (`ros2/src/craic_localization/`)
- `udp_control.py` - 命令行机械臂控制(支持逆运动学)
- `camera_to_base.py` - 坐标变换工具
- `camera_capture.py` - 相机帧采集(支持自动扫描)
三个阶段式比赛流程:
| 阶段 | Launch 文件 | 功能 | TF 链 |
|------|------------|------|-------|
| P3 标定 | `bringup.launch.py` | 轮式里程计 + 激光驱动 + RViz | `odom → base_footprint → laser_frame` |
| P4 建图 | `mapping.launch.py` | 激光 + rf2o 里程计 + slam_gmapping | `map → odom → base_footprint → laser_frame` |
| P5 导航 | `localization.launch.py` | 激光 + rf2o + map_server + AMCL | `map → odom → base_footprint → laser_frame` |
**定位系统节点**
| 节点 | 功能 |
|------|------|
| `chassis_odometry` | 串口读取 LZUCAR 底盘 MCU 轮式里程计32 字节协议) |
| `teach_points` | 交互式示教工具:回车记录 map 帧位姿,支持预设点位序列 (B_1..F_1),自动存 YAML |
| `navigate_to_point` | 全向 P 控制器自主导航到示教点UDP XYW 指令闭环驱动,干运行/单次模式可选 |
| `show_points` | RViz MarkerArray 可视化示教点(箭头 + 标签),实时更新 |
### 4. 命令行工具 (`tools/`)
| 工具 | 功能 |
|------|------|
| `udp_control.py` | 机械臂关节/笛卡尔空间控制,逆运动学,轨迹插值,状态缓存,干运行 |
| `camera_to_base.py` | 相机→TCP→基座完整变换链支持相机安装偏移与旋转 |
| `camera_capture.py` | ESP32 MJPEG 流帧采集,自动子网扫描寻找相机 |
| `udp_server.py` | UDP 回显服务器,用于调试协议通信 |
## 快速开始
@@ -83,8 +131,6 @@ pio run -t upload
pio device monitor
```
首次启动创建热点 `ESP32-S3-Camera`(密码 `12345678`),访问 `http://192.168.4.1`
### ROS 2 控制系统
```bash
@@ -92,124 +138,187 @@ pio device monitor
conda create -n ros2_humble -c robostack-staging -c conda-forge ros-humble-desktop
conda activate ros2_humble
# 编译
# 编译(一键)
cd ros2
export PYTHON_EXECUTABLE=$CONDA_PREFIX/bin/python
export PYTHON_INCLUDE_DIR=$CONDA_PREFIX/include/python3.12
export PYTHON_LIBRARY=$CONDA_PREFIX/lib/libpython3.12.so
colcon build --packages-select arm_control_msgs \
--cmake-args \
-DPython_EXECUTABLE=$PYTHON_EXECUTABLE \
-DPython_INCLUDE_DIR=$PYTHON_INCLUDE_DIR \
-DPython_LIBRARY=$PYTHON_LIBRARY
colcon build --packages-select udp_teleop
./build.sh
source install/setup.bash
# 运行机械臂控制
# 或按需编译指定包
./build.sh --packages-select craic_localization udp_teleop
```
**启动机械臂控制**
```bash
# 终端 1机械臂控制器
ros2 run udp_teleop arm_control \
--ros-args --params-file src/udp_teleop/config/arm_control.yaml
# 运行视觉抓取(新终端)
# 终端 2视觉抓取
ros2 run udp_teleop vision_grasp \
--ros-args --params-file src/udp_teleop/config/vision_grasp.yaml
# 或一键启动全部(含 YOLO 检测)
ros2 launch udp_teleop vision_grasp.launch.py detection:=true auto_grasp:=true
```
**启动键盘遥控**
```bash
ros2 run udp_teleop keyboard_control \
--ros-args --params-file src/udp_teleop/config/params.yaml
```
**启动定位与导航**
```bash
# P4 建图
ros2 launch craic_localization mapping.launch.py
# 建图完成后保存
ros2 run nav2_map_server map_saver_cli -f src/craic_localization/maps/craic
# P5 定位 + 导航
ros2 launch craic_localization localization.launch.py
# 新终端:示教记录点位
ros2 run craic_localization teach_points \
--ros-args -p output_file:=$PWD/src/craic_localization/config/taught_points.yaml
# 新终端:自主导航到示教点
ros2 run craic_localization navigate_to_point
```
### 命令行工具
```bash
# 机械臂控制(关节空间)
python tools/udp_control.py joints \
--height -100 --j2 10 --j3 20 --j4 30 --duration 2.0
# 机械臂控制(笛卡尔空间)
python tools/udp_control.py pose \
--x 200 --y 100 --z -100 --phi 45 --duration 2.0
# 机械臂控制
python tools/udp_control.py pose --x 200 --y 100 --z -100 --phi 45 --duration 2.0
python tools/udp_control.py joints --height -100 --j2 10 --j3 20 --j4 30
# 相机采集
python tools/camera_capture.py --ip 192.168.4.1
python tools/camera_capture.py --scan # 自动扫描
# UDP 调试
python tools/udp_server.py
echo 'XYW:100:0:0:XZHY' | nc -u 127.0.0.1 8888
```
## UDP 协议
所有指令通过 UDP 端口 `8888` 发送:
所有指令通过 UDP 端口 `8888` 发送ASCII 文本协议
```bash
# 底盘控制(麦克纳姆轮)
XYW:<X>:<Y>:<W>:XZHY\n
```
# 底盘控制(麦克纳姆轮全向速度
XYW:<X_speed>:<Y_speed>:<W_angular>:XZHY\n
# 机械臂控制6 轴)
# 机械臂控制6 轴角度 + 高度
JXB:<height>:<J2>:<J3>:<J4>:<J5>:<J6>:0:0:EZHY\n
# 激光控制
LASERON / LASEROFF
LASERON\n
LASEROFF\n
```
- 角度单位:度(已包含零点偏移)
- 高度单位mm
- 速度单位X/Y mm/sW deg/s
## 使用示例
### ROS 服务调用
```bash
# 查询位姿
ros2 service call /arm_control/get_pose arm_control_msgs/srv/GetPose
# 移动到目标位置
# 机械臂移动到目标位置
ros2 service call /arm_control/move_pose arm_control_msgs/srv/MovePose \
"{x: 200.0, y: 100.0, z: -100.0, phi: 45.0, duration: 2.0}"
# 快速抓取
ros2 service call /arm_control/move_pose arm_control_msgs/srv/MovePose \
"{x: 200.0, y: 100.0, z: -100.0, phi: 45.0, grip: true, duration: 2.0}"
# 查询位姿
ros2 service call /arm_control/get_pose arm_control_msgs/srv/GetPose
# 视觉抓取(发布相机坐标)
ros2 topic pub --once /vision_grasp/grasp_target geometry_msgs/Point \
"{x: 10.0, y: 5.0, z: 250.0}"
```
### 定位导航工作流
```bash
# 1. 启动定位系统
ros2 launch craic_localization localization.launch.py
# 2. 键盘遥控到目标位置(另一终端)
ros2 run udp_teleop keyboard_control \
--ros-args --params-file src/udp_teleop/config/params.yaml
# 3. 示教记录点位(第三终端)
ros2 run craic_localization teach_points \
--ros-args -p output_file:=$PWD/src/craic_localization/config/taught_points.yaml
# 交互命令:回车记录 → r 记录 → p 查看 → save 保存 → q 退出
# 4. 自主导航到示教点
ros2 run craic_localization navigate_to_point
# 输入目标点名(如 B_1机器人自动导航到位
```
### Python 集成
```python
import rclpy
from geometry_msgs.msg import Point
class VisionDetector:
class VisionDetector(rclpy.node.Node):
def __init__(self):
self.grasp_pub = self.create_publisher(Point, 'vision_grasp/grasp_target', 10)
super().__init__('vision_detector')
self.grasp_pub = self.create_publisher(
Point, 'vision_grasp/grasp_target', 10)
def on_detection(self, camera_x, camera_y, camera_z):
msg = Point()
msg.x = camera_x
msg.y = camera_y
msg.z = camera_z
msg.x = camera_x; msg.y = camera_y; msg.z = camera_z
self.grasp_pub.publish(msg)
```
## 文档
- **ROS 2 系统**[ros2/README.md](ros2/README.md) - 完整的 ROS 节点文档
- **运动学推导**[docs/arm.md](docs/arm.md) - 机械臂逆运动学数学推导
- **视觉标定**[docs/vision_calibration_horizontal.md](docs/vision_calibration_horizontal.md) - 相机标定指南
## 坐标系说明
**机械臂基坐标系**Z 轴朝上):
- 原点J1 线性滑轨底部
- X 轴:基座正前方
- Y 轴:基座左侧
- Z 轴:竖直向上(高度)
- X 轴:基座正前方Y 轴基座左侧Z 轴:竖直向上
- 单位mm
**相机坐标系**(水平安装):
- X 轴:右侧
- Y 轴:向下
- Z 轴:正前方(光轴)
- X 轴:右侧Y 轴向下Z 轴:正前方(光轴)
- 单位mm
变换由 `camera_to_base.py``vision_grasp` 节点自动处理。
**底盘坐标系**ROS TF
```
map ──(AMCL)──> odom ──(rf2o)──> base_footprint ──(static)──> laser_frame
──(static)──> base_link
```
- `map`全局固定坐标系AMCL 定位输出)
- `odom`连续里程计坐标系rf2o 激光里程计)
- `base_footprint`:底盘投影中心
- `laser_frame`:激光雷达安装位置(外参可调:`lidar_x`, `lidar_y`, `lidar_yaw`
## 文档
| 文档 | 说明 |
|------|------|
| [docs/arm.md](docs/arm.md) | 机械臂逆运动学完整数学推导2 连杆平面臂 + z4 偏移) |
| [docs/localization.md](docs/localization.md) | 定位系统文档SLAM 建图、AMCL 定位、示教导航、故障排查 |
| [docs/box_detection_grasp.md](docs/box_detection_grasp.md) | YOLO 方框检测与自动抓取:配置、服务、深度估计原理 |
| [ros2/README.md](ros2/README.md) | ROS 2 节点详细文档 |
| [tools/README.md](tools/README.md) | 命令行工具完整参数与工作流示例 |
## 依赖
| 环境 | 依赖 |
|------|------|
| ESP32 | PlatformIO, Arduino framework, esp32-camera |
| ROS 2 | ROS 2 Humble (robostack), Python 3.12 |
| 工具 | NumPy, OpenCV (可选) |
| ROS 2 | ROS 2 Humble, `slam_gmapping`, `nav2_amcl`, `nav2_map_server`, `nav2_lifecycle_manager`, `serial` |
| Python | NumPy, OpenCV, Ultralytics (YOLO), pynput (可选) |
| 系统 | YDLidar-SDK, colcon, conda (robostack) |
## 许可