Add G20 calibration assets, L20 compare, and refresh README.
Sync calibrated G20 URDF/MJCF/JSON lookup, L20 V10.1 dual-compare scripts, joint GUI, and document O6/G20/L20 startup on the Gitea repo. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,15 +1,22 @@
|
||||
# LinkerHand O6 MuJoCo(ROS2)启动说明
|
||||
# Mujoco LinkerBot(ROS 2)
|
||||
|
||||
本机跑 MuJoCo 左手仿真,可用本机或另一台电脑通过 ROS2 话题控制。
|
||||
Linker Hand 的 MuJoCo + ROS 2 仿真工作区。支持:
|
||||
|
||||
- **O6**:经典 6 通道 0~255 控制(launch)
|
||||
- **G20 左手**:PLAN 桥接、标定查表、MJCF/URDF 零位同步
|
||||
- **L20 V10.1 左手**:与 G20 双窗对比
|
||||
- 关节弧度监视 GUI、曲线录制与实验脚本
|
||||
|
||||
远程仓库:<https://gitea.robotquan.com/sunxianghui/mujoco_linkerbot.git>
|
||||
|
||||
---
|
||||
|
||||
## 环境要求
|
||||
|
||||
- Ubuntu + ROS 2 **Jazzy**
|
||||
- 工作区路径:`~/linker_hand_mujoco_ros2`
|
||||
- Python 依赖在 `venv` 中(含 `mujoco`、`PyQt5`)
|
||||
- **注意**:`ros2 launch` 使用系统 `/usr/bin/python3`,仅 `source venv` **不够**,需用下文的启动脚本或设置 `PYTHONPATH`
|
||||
- 工作区路径示例:`~/linker_hand_mujoco_ros2`
|
||||
- Python 依赖在本地 `venv`(含 `mujoco` 等;**不要**把 `venv` 提交进仓库)
|
||||
- `ros2 launch` 使用系统 Python,仅 `source venv` 不够,请用仓库里的启动脚本(会把 `venv/site-packages` 加入 `PYTHONPATH`)
|
||||
|
||||
---
|
||||
|
||||
@@ -22,53 +29,19 @@ colcon build --symlink-install --packages-select linker_hand_mujoco_ros2
|
||||
source install/setup.bash
|
||||
```
|
||||
|
||||
`venv` 目录已放 `COLCON_IGNORE`,不会被 colcon 误扫。
|
||||
`venv/` 已放 `COLCON_IGNORE`,不会被 colcon 误扫。
|
||||
|
||||
---
|
||||
|
||||
## 二、本机启动仿真(推荐)
|
||||
## 二、O6 仿真(原有流程)
|
||||
|
||||
```bash
|
||||
cd ~/linker_hand_mujoco_ros2
|
||||
./run_sim.sh
|
||||
```
|
||||
|
||||
脚本会自动:
|
||||
|
||||
- `source` ROS2 与本工作区
|
||||
- `ROS_DOMAIN_ID=30`,`ROS_LOCALHOST_ONLY=0`(便于多机)
|
||||
- 把 `venv` 的 `site-packages` 加入 `PYTHONPATH`(解决找不到 `mujoco`)
|
||||
|
||||
成功后应出现:
|
||||
|
||||
1. MuJoCo 3D 窗口(左手 O6)
|
||||
2. Joint 进度条窗口(实时关节角)
|
||||
|
||||
### 手动启动(等效)
|
||||
|
||||
```bash
|
||||
cd ~/linker_hand_mujoco_ros2
|
||||
source /opt/ros/jazzy/setup.bash
|
||||
source install/setup.bash
|
||||
export PYTHONPATH="$PWD/venv/lib/python3.12/site-packages:$PYTHONPATH"
|
||||
ros2 launch linker_hand_mujoco_ros2 linker_hand_mujoco_ros2.launch.py
|
||||
```
|
||||
|
||||
当前 launch 默认:
|
||||
|
||||
| 参数 | 值 |
|
||||
|------|-----|
|
||||
| `hand_type` | `left` |
|
||||
| `hand_joint` | `O6` |
|
||||
| 控制话题 | `/cb_left_hand_control_cmd` |
|
||||
|
||||
---
|
||||
|
||||
## 三、控制话题说明
|
||||
|
||||
- 话题:`/cb_left_hand_control_cmd`
|
||||
- 控制话题:`/cb_left_hand_control_cmd`
|
||||
- 类型:`sensor_msgs/msg/JointState`
|
||||
- `position`:**6 个数**,范围约 **0–255**
|
||||
- `position`:6 个数,约 **0~255**(**255≈张开,0≈握紧**)
|
||||
|
||||
| 索引 | 含义 |
|
||||
|------|------|
|
||||
@@ -79,9 +52,119 @@ ros2 launch linker_hand_mujoco_ros2 linker_hand_mujoco_ros2.launch.py
|
||||
| 4 | 无名指弯曲 |
|
||||
| 5 | 小指弯曲 |
|
||||
|
||||
约定(当前映射):约 **255 = 张开,0 = 握紧**。远指节由 mimic 跟随近指节。
|
||||
更多 O6 / 多机 DDS / 曲线录制说明见下文「附录:O6 与多机」。
|
||||
|
||||
### 本机发一帧(握拳示例)
|
||||
---
|
||||
|
||||
## 三、G20 左手仿真(推荐)
|
||||
|
||||
### 3.1 一键启动
|
||||
|
||||
```bash
|
||||
./run_g20_mujoco_plan.sh
|
||||
```
|
||||
|
||||
默认行为:
|
||||
|
||||
| 项 | 值 |
|
||||
|----|-----|
|
||||
| 模型 | `urdf/G20/linker_hand_g20_left/linker_hand_g20_left.xml` |
|
||||
| 控制话题 | `/g20/cb_left_hand_control_cmd` |
|
||||
| 状态话题 | `/sim/mujoco/g20/left/joint_state` |
|
||||
| 指令 | 20 维 0~255(与真机 SDK 通道对齐) |
|
||||
| 映射 | 标定 JSON 查表 + URDF 被动 mimic |
|
||||
| 速度 | 约 1.35× 墙钟,可用 `--speed` / `--slew-rad-s` 调整 |
|
||||
|
||||
常用参数示例:
|
||||
|
||||
```bash
|
||||
./run_g20_mujoco_plan.sh --speed 1.0
|
||||
./run_g20_mujoco_plan.sh --cmd-topic /g20/cb_left_hand_control_cmd
|
||||
./run_g20_mujoco_plan.sh --mapping g20_calibrated
|
||||
```
|
||||
|
||||
### 3.2 关节弧度 GUI
|
||||
|
||||
```bash
|
||||
./run_g20_joint_gui.sh
|
||||
```
|
||||
|
||||
默认订阅 `/sim/mujoco/g20/left/joint_state`,按手指分组显示 hinge 弧度(默认 6 位小数)。
|
||||
|
||||
### 3.3 G20 + L20 双窗对比
|
||||
|
||||
```bash
|
||||
./run_dual_mujoco_compare.sh
|
||||
```
|
||||
|
||||
- 左窗:当前标定 **G20**(`g20_calibrated`)
|
||||
- 右窗:**L20 V10.1** 原版 URDF 映射(`l20_urdf`,默认关 collision project,避免自碰卡住)
|
||||
- 共用同一条 0~255 控制话题(默认 `/g20/cb_left_hand_control_cmd`)
|
||||
|
||||
---
|
||||
|
||||
## 四、标定与模型文件(G20)
|
||||
|
||||
目录:
|
||||
|
||||
`src/linkerhand-sim/linker_hand_mujoco_ros2/linker_hand_mujoco_ros2/urdf/G20/linker_hand_g20_left/`
|
||||
|
||||
| 文件 | 说明 |
|
||||
|------|------|
|
||||
| `linkerhand_g20_left.urdf` | 当前使用的 URDF(含投影零位修正) |
|
||||
| `linker_hand_g20_left.xml` | 当前使用的 MJCF(与 URDF 原点/限位同步) |
|
||||
| `g20_left_G20_LEFT_001_calibration.json` | 运行时 0~255→弧度查表(schema 3) |
|
||||
| `meshes/` | 网格 |
|
||||
|
||||
映射实现:`utils/g20_joints.py`
|
||||
|
||||
要点:
|
||||
|
||||
1. **主动关节**:用标定 JSON 的 `angle_rad[0..255]` 查表。
|
||||
2. **零位**:用 `zero_angles.table_projected_zero_rad` 相对夹具参考修正 URDF/MJCF `origin`(相机投影零位,非完整外参优化)。
|
||||
3. **被动关节**:`thumb_ip`、四指 DIP 走 URDF mimic;JSON 里 `thumb_ip` 是累计投影角,**不能**直接当相对关节角。
|
||||
4. **四指侧摆**:运行时符号与真机约定见 `G20_FLIP_JOINT_SIGN`。
|
||||
|
||||
当前已知:张开大姿态已基本对齐;拇指 CMC 零位仍可能有小量前探/拧向残差。更稳妥的做法是解耦重测三个 CMC 投影零位,或导出 TAG 全位姿后做原点优化,而不是肉眼加减角度。
|
||||
|
||||
---
|
||||
|
||||
## 五、主要源码入口
|
||||
|
||||
| 路径 | 说明 |
|
||||
|------|------|
|
||||
| `linker_hand_mujoco_ros2/g20_plan_bridge.py` | G20/L20 MuJoCo PLAN 桥 |
|
||||
| `linker_hand_mujoco_ros2/g20_joint_monitor_gui.py` | 关节弧度监视 GUI |
|
||||
| `linker_hand_mujoco_ros2/utils/g20_joints.py` | G20 标定查表与映射 |
|
||||
| `launch/linker_hand_mujoco_ros2.launch.py` | O6 launch |
|
||||
| `urdf/O6/` | O6 MJCF |
|
||||
| `urdf/G20/` | G20 URDF/MJCF + 标定 |
|
||||
| `urdf/L20_V10.1/` | L20 V10.1 URDF/MJCF |
|
||||
| `tools/` | 曲线录制、实验脚本 |
|
||||
|
||||
Console 入口(`setup.py`):`g20_plan_bridge`、`g20_joint_monitor_gui` 等。
|
||||
|
||||
---
|
||||
|
||||
## 六、克隆与推送
|
||||
|
||||
```bash
|
||||
git clone https://gitea.robotquan.com/sunxianghui/mujoco_linkerbot.git
|
||||
cd mujoco_linkerbot
|
||||
# 自建 venv 并安装 mujoco 等依赖后,再 colcon build
|
||||
```
|
||||
|
||||
本仓库 `origin` 指向上述 Gitea 地址。提交后:
|
||||
|
||||
```bash
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 附录:O6 与多机
|
||||
|
||||
### 本机发一帧(O6 握拳示例)
|
||||
|
||||
```bash
|
||||
source /opt/ros/jazzy/setup.bash
|
||||
@@ -97,187 +180,36 @@ ros2 topic pub --once /cb_left_hand_control_cmd sensor_msgs/msg/JointState "{
|
||||
}"
|
||||
```
|
||||
|
||||
张开:
|
||||
### 两台电脑共用 ROS 2
|
||||
|
||||
```bash
|
||||
ros2 topic pub --once /cb_left_hand_control_cmd sensor_msgs/msg/JointState "{
|
||||
header: {stamp: {sec: 0, nanosec: 0}, frame_id: ''},
|
||||
name: [],
|
||||
position: [255.0, 255.0, 255.0, 255.0, 255.0, 255.0],
|
||||
velocity: [],
|
||||
effort: []
|
||||
}"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、两台电脑共用 ROS2
|
||||
|
||||
ROS2 **没有** ROS1 的 `roscore`。两边约定同一个 Domain 即可。
|
||||
|
||||
### 两边都设置
|
||||
两边约定同一 Domain:
|
||||
|
||||
```bash
|
||||
export ROS_DOMAIN_ID=30
|
||||
export ROS_LOCALHOST_ONLY=0
|
||||
```
|
||||
|
||||
### 电脑 A:仿真机
|
||||
仿真机跑 `./run_sim.sh` 或 `./run_g20_mujoco_plan.sh`;控制机 `ros2 topic list` / `hz` / `echo` 检查。
|
||||
|
||||
```bash
|
||||
cd ~/linker_hand_mujoco_ros2
|
||||
./run_sim.sh
|
||||
```
|
||||
|
||||
### 电脑 B:控制机(发指令 / handretarget / SDK)
|
||||
### 通用曲线录制
|
||||
|
||||
```bash
|
||||
source /opt/ros/jazzy/setup.bash
|
||||
export ROS_DOMAIN_ID=30
|
||||
export ROS_LOCALHOST_ONLY=0
|
||||
|
||||
# 确认话题与收发端
|
||||
ros2 topic list
|
||||
ros2 topic info /cb_left_hand_control_cmd -v
|
||||
```
|
||||
|
||||
`topic info -v` 中应能看到:
|
||||
|
||||
- **Publisher**:例如 `handretarget_node`
|
||||
- **Subscription**:至少包含 `linker_hand_mujoco_ros2_node`
|
||||
|
||||
### 查是否真的在发数据
|
||||
|
||||
有 Publisher ≠ 正在发数据。请用:
|
||||
|
||||
```bash
|
||||
ros2 topic hz /cb_left_hand_control_cmd
|
||||
ros2 topic echo /cb_left_hand_control_cmd
|
||||
```
|
||||
|
||||
- `hz` 无输出 → 对端没在 publish
|
||||
- `echo --once` 会一直等到有一帧;无数据时像卡住,优先用上面两条
|
||||
|
||||
### 跨机能看见话题但收不到数据时
|
||||
|
||||
1. 确认两边 `ROS_DOMAIN_ID`、`ROS_LOCALHOST_ONLY=0` 一致,并重启节点
|
||||
2. 互相 `ping` 通;尽量同一网段 / 有线;关闭路由器 **AP 隔离**
|
||||
3. 本机 `ufw` 可先确认:`sudo ufw status`(不活动则不是防火墙)
|
||||
4. 需要时可配置 CycloneDDS 静态 Peer(两边 IP 写入 `~/cyclonedds.xml`),然后:
|
||||
|
||||
```bash
|
||||
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
|
||||
export CYCLONEDDS_URI=file://$HOME/cyclonedds.xml
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、常用自检命令
|
||||
|
||||
```bash
|
||||
# 节点是否在
|
||||
ros2 node list
|
||||
|
||||
# 话题列表(仿真未启动时可能还没有 /cb_left_hand_control_cmd)
|
||||
ros2 topic list
|
||||
|
||||
# 订阅/发布数量与节点名
|
||||
ros2 topic info /cb_left_hand_control_cmd -v
|
||||
|
||||
# 频率 / 内容
|
||||
ros2 topic hz /cb_left_hand_control_cmd
|
||||
ros2 topic echo /cb_left_hand_control_cmd
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、常见问题
|
||||
|
||||
### `ModuleNotFoundError: No module named 'mujoco'`
|
||||
|
||||
`ros2 launch` 没用到 venv。请用:
|
||||
|
||||
```bash
|
||||
./run_sim.sh
|
||||
```
|
||||
|
||||
或设置 `PYTHONPATH`(见上文「手动启动」)。
|
||||
|
||||
### `topic list` 只有 `/rosout`,没有左手话题
|
||||
|
||||
仿真节点未运行。先 `./run_sim.sh`,再 `ros2 topic list`。
|
||||
|
||||
### 改左右手
|
||||
|
||||
编辑:
|
||||
|
||||
`src/linkerhand-sim/linker_hand_mujoco_ros2/launch/linker_hand_mujoco_ros2.launch.py`
|
||||
|
||||
- 左手:`hand_type: 'left'` → 话题 `/cb_left_hand_control_cmd`
|
||||
- 右手:`hand_type: 'right'` → 话题 `/cb_right_hand_control_cmd`
|
||||
|
||||
改完后若未用 symlink,再执行一次 `colcon build --symlink-install`。
|
||||
|
||||
---
|
||||
|
||||
## 七、通用曲线录制(仿真 / 真机同一套话题)
|
||||
|
||||
**只传一个文件给对端即可:**
|
||||
|
||||
`tools/hand_curve_recorder_standalone.py`
|
||||
|
||||
两边都要:已 `source` ROS2、`numpy`、`matplotlib`。
|
||||
|
||||
```bash
|
||||
source /opt/ros/jazzy/setup.bash
|
||||
export ROS_DOMAIN_ID=30
|
||||
export ROS_LOCALHOST_ONLY=0
|
||||
|
||||
# 仿真端
|
||||
python3 tools/hand_curve_recorder_standalone.py --hand left --channel 3 --label sim
|
||||
|
||||
# 真机端(把该 py 拷过去后)
|
||||
python3 hand_curve_recorder_standalone.py --hand left --channel 3 --label real
|
||||
```
|
||||
|
||||
对端发 `/cb_left_hand_control_cmd`;本机 **Ctrl+C** → `reports/hand_curves/` 下生成 csv + 三曲线图。
|
||||
### 常见问题
|
||||
|
||||
默认还订 `/cb_left_hand_state`(`position`=0~255,`effort` 可放电流)。话题名不同时:
|
||||
**`ModuleNotFoundError: No module named 'mujoco'`**
|
||||
用 `./run_sim.sh` / `./run_g20_mujoco_plan.sh`,或手动把 `venv/lib/python3.12/site-packages` 加入 `PYTHONPATH`。
|
||||
|
||||
```bash
|
||||
python3 hand_curve_recorder_standalone.py --state-topic /你的状态话题 --channel 3 --label real
|
||||
```
|
||||
|
||||
通道:`0拇指弯 1拇指横摆 2食指 3中指 4无名指 5小指`。
|
||||
**L20 双窗对比时手不动**
|
||||
自碰投影会把目标打回;`run_dual_mujoco_compare.sh` 已对 L20 默认 `--no-collision-project`。
|
||||
|
||||
---
|
||||
|
||||
要「ROS 发指令 + 仿真里出 q/v/τ 图」:
|
||||
## 许可与归属
|
||||
|
||||
```bash
|
||||
cd ~/linker_hand_mujoco_ros2
|
||||
source /opt/ros/jazzy/setup.bash
|
||||
export ROS_DOMAIN_ID=30
|
||||
export ROS_LOCALHOST_ONLY=0
|
||||
|
||||
# 自测:订话题 + 本地 MuJoCo + 自动发中指慢扫 + 可选 viewer
|
||||
./venv/bin/python tools/ros_mujoco_record_qvt.py \
|
||||
--hand left --finger middle --viewer --self-sweep
|
||||
|
||||
# 对端发指令时:去掉 --self-sweep
|
||||
./venv/bin/python tools/ros_mujoco_record_qvt.py \
|
||||
--hand left --finger middle --viewer
|
||||
# Ctrl+C → reports/O6_middle_ros/*_qvt.png
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、文件与模型位置
|
||||
|
||||
| 路径 | 说明 |
|
||||
|------|------|
|
||||
| `./run_sim.sh` | 本机一键启动 |
|
||||
| `src/.../launch/linker_hand_mujoco_ros2.launch.py` | 左右手 / 型号 |
|
||||
| `src/.../urdf/O6/` | O6 左右手 MJCF(来自 mujoco_testwork 验证模型) |
|
||||
| `src/.../utils/joint_monitor.py` | Joint 进度条 UI |
|
||||
| `venv/` | Python 依赖(勿放进 colcon 扫描,已 IGNORE) |
|
||||
包内模型与标定数据来自 Linker Hand / 本机标定流程;请按公司内部仓库规范使用与分发。
|
||||
|
||||
Reference in New Issue
Block a user