初始化仓库提交
This commit is contained in:
@@ -0,0 +1,77 @@
|
|||||||
|
---
|
||||||
|
name: commit
|
||||||
|
description: 自动生成中文 git commit 信息并提交推送。读取当前改动,用简洁的中文一句话概括改动内容,然后自动执行 git add、commit、push。当用户说"提交""commit""提交代码""推送"时使用。
|
||||||
|
allowed-tools: Bash(git status:*), Bash(git diff:*), Bash(git add:*), Bash(git commit:*), Bash(git push:*), Bash(git log:*), Bash(git branch:*)
|
||||||
|
---
|
||||||
|
|
||||||
|
# 自动 commit 并 push
|
||||||
|
|
||||||
|
读取当前 git 改动,生成简洁的中文 commit 信息,然后自动提交并推送。
|
||||||
|
|
||||||
|
## 执行步骤
|
||||||
|
|
||||||
|
### 1. 查看当前状态
|
||||||
|
|
||||||
|
先了解仓库当前情况:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git status
|
||||||
|
git diff --stat # 看改动了哪些文件、改动量
|
||||||
|
git diff # 看未暂存的具体改动
|
||||||
|
git diff --staged # 看已暂存的具体改动
|
||||||
|
git log --oneline -5 # 看最近几次提交风格,保持一致
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 分析改动
|
||||||
|
|
||||||
|
基于 diff 内容,理解这次改动**实际做了什么**:
|
||||||
|
|
||||||
|
- 新增了什么功能/文件
|
||||||
|
- 修改/修复了什么
|
||||||
|
- 删除/重构了什么
|
||||||
|
- 是文档、配置还是代码改动
|
||||||
|
|
||||||
|
**不要凭文件名猜测,要看实际 diff 内容。**
|
||||||
|
|
||||||
|
### 3. 生成 commit 信息
|
||||||
|
|
||||||
|
要求:
|
||||||
|
|
||||||
|
- **中文**,简洁,**一句话**概括这次改动的核心内容
|
||||||
|
- **不要前缀**(不用 feat/fix/docs 这种 Conventional Commits 前缀)
|
||||||
|
- 直接描述做了什么,动词开头,如"添加 ALNS 自适应大邻域搜索算法"、"修复 POX 交叉中的索引越界问题"、"重构 FJSP 解码逻辑去掉 AGV 部分"
|
||||||
|
- 如果一次改动包含多个不相关的事情,提示用户是否要分开提交(但默认仍按一条处理)
|
||||||
|
- 长度控制在一行能看完,不写冗长描述
|
||||||
|
|
||||||
|
### 4. 自动提交并推送
|
||||||
|
|
||||||
|
确认 commit 信息后,依次执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add -A # 暂存所有改动
|
||||||
|
git commit -m "生成的中文commit信息"
|
||||||
|
git push # 推送到当前分支的远程
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. 处理常见情况
|
||||||
|
|
||||||
|
- **没有改动**:如果 `git status` 显示没有改动,告知用户无需提交,停止
|
||||||
|
- **push 失败**:
|
||||||
|
- 如果是因为远程有新提交(需要先 pull),告知用户,建议先 `git pull` 或 `git pull --rebase`,**不要自动强推**
|
||||||
|
- 如果是没有配置远程或没有 upstream 分支,提示用户,给出 `git push -u origin <分支名>` 的建议命令
|
||||||
|
- 如果是认证问题,告知用户检查凭证
|
||||||
|
- **当前在重要分支**(如 main/master):正常执行,但在输出里提示一下当前分支名,让用户心里有数
|
||||||
|
|
||||||
|
### 6. 输出
|
||||||
|
|
||||||
|
完成后简要报告:
|
||||||
|
|
||||||
|
- 生成的 commit 信息
|
||||||
|
- 提交到了哪个分支
|
||||||
|
- push 是否成功
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
- commit 信息必须如实反映 diff 内容,不编造
|
||||||
|
- push 失败时不要用 `--force` 强推,交给用户决定
|
||||||
|
- 如果改动很大很杂,主动提示用户考虑拆分提交,但不强制
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
---
|
||||||
|
name: readme
|
||||||
|
description: 为当前项目生成适配 Gitee / 公司内部代码仓库的中英文双语 README。默认生成 README.md(中文,Gitee 默认展示)和 README_en.md(英文)两个文件,顶部互相链接切换语言。适用于公司项目、算法项目、机器人项目、工程代码仓库。当用户说“写个README”“生成项目介绍”“生成Gitee README”“make a readme”时使用。
|
||||||
|
---
|
||||||
|
|
||||||
|
# Gitee 双语 README 生成
|
||||||
|
|
||||||
|
为当前项目生成两个互相链接的 README 文件:
|
||||||
|
|
||||||
|
- `README.md`:简体中文,作为 Gitee 默认展示文件
|
||||||
|
- `README_en.md`:英文版,供中英文切换使用
|
||||||
|
|
||||||
|
如果项目中已经存在 `README_zh.md`、`Readme_zh.md`、`Readme_en.md` 等命名,先读取已有文件,并尽量沿用当前仓库已有命名规范;如果没有明确规范,默认使用 `README.md` + `README_en.md`。
|
||||||
|
|
||||||
|
## 执行目标
|
||||||
|
|
||||||
|
生成符合公司内部 Gitee 仓库风格的 README,不写成 GitHub 开源宣传页。
|
||||||
|
|
||||||
|
README 应该让新同事或项目参与者快速知道:
|
||||||
|
|
||||||
|
- 项目是什么
|
||||||
|
- 面向什么设备 / 平台 / 场景
|
||||||
|
- 软件架构大概是什么
|
||||||
|
- 如何安装依赖
|
||||||
|
- 如何编译 / 运行 / 启动
|
||||||
|
- 代码目录怎么组织
|
||||||
|
- 如何按公司流程参与开发
|
||||||
|
|
||||||
|
## 执行步骤
|
||||||
|
|
||||||
|
### 1. 调研项目
|
||||||
|
|
||||||
|
先充分了解项目,不要凭空编造内容。
|
||||||
|
|
||||||
|
必须优先读取和分析:
|
||||||
|
|
||||||
|
- 项目根目录结构
|
||||||
|
- 已有 README / 文档
|
||||||
|
- 主入口脚本
|
||||||
|
- 启动脚本
|
||||||
|
- `CMakeLists.txt`
|
||||||
|
- `package.xml`
|
||||||
|
- `requirements.txt`
|
||||||
|
- `pyproject.toml`
|
||||||
|
- `package.json`
|
||||||
|
- `docker-compose.yml`
|
||||||
|
- `Dockerfile`
|
||||||
|
- 配置文件
|
||||||
|
- 核心源码目录
|
||||||
|
|
||||||
|
需要识别:
|
||||||
|
|
||||||
|
- 项目名称
|
||||||
|
- 项目用途
|
||||||
|
- 运行平台
|
||||||
|
- 技术栈
|
||||||
|
- 编程语言
|
||||||
|
- 构建方式
|
||||||
|
- 启动方式
|
||||||
|
- 主要模块
|
||||||
|
- 依赖项
|
||||||
|
|
||||||
|
**重要:只写代码和文档中真实存在的内容。**
|
||||||
|
|
||||||
|
不要编造:
|
||||||
|
|
||||||
|
- 未确认的算法
|
||||||
|
- 未确认的性能指标
|
||||||
|
- 未确认的硬件型号
|
||||||
|
- 未确认的启动命令
|
||||||
|
- 未确认的部署流程
|
||||||
|
- 未确认的许可证
|
||||||
|
|
||||||
|
如果信息不足,用“待补充”明确标注,不要用通用模板假装完整。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 文件命名与语言切换
|
||||||
|
|
||||||
|
### 默认文件
|
||||||
|
|
||||||
|
生成:
|
||||||
|
|
||||||
|
```text
|
||||||
|
README.md
|
||||||
|
README_en.md
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
# 技术报告 LaTeX 模板
|
||||||
|
|
||||||
|
[简体中文](README.md) | [English](README_en.md)
|
||||||
|
|
||||||
|
这是一个面向中文技术报告的 LaTeX 模板,适合整理项目设计、实现说明、测试结果、问题排查、常见问题和后续规划等内容。仓库同时提供空白模板与两个完整示例,可直接复制后修改。
|
||||||
|
|
||||||
|
## 模板特点
|
||||||
|
|
||||||
|
- A4 纸张、12 pt 字号、2.5 cm 页边距和 1.5 倍行距
|
||||||
|
- 包含封面、自动目录、页眉页脚和版本信息
|
||||||
|
- 预设多级章节标题、超链接和配色
|
||||||
|
- 支持代码块、数学公式、表格、图片和列表
|
||||||
|
- 提供文件说明框、问答框等技术文档常用样式
|
||||||
|
- 已配置 Python 与 Bash 代码高亮样式
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```text
|
||||||
|
.
|
||||||
|
├─ 模板/
|
||||||
|
│ ├─ main.tex # 可直接修改的空白模板
|
||||||
|
│ └─ 模板.pdf # 模板编译效果
|
||||||
|
├─ example/
|
||||||
|
│ ├─ 停车机器人example/
|
||||||
|
│ │ ├─ main.tex # 技术问题排查类报告示例
|
||||||
|
│ │ ├─ *.png # 示例使用的图片
|
||||||
|
│ │ └─ *.pdf # 已编译的示例文档
|
||||||
|
│ └─ 旧版个人example/
|
||||||
|
│ ├─ main.tex # 较完整的个人技术报告示例
|
||||||
|
│ ├─ *.png # 示例使用的图片
|
||||||
|
│ └─ *.pdf # 已编译的示例文档
|
||||||
|
├─ README.md
|
||||||
|
└─ README_en.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## 环境要求
|
||||||
|
|
||||||
|
请安装带有 XeLaTeX 的 LaTeX 发行版,例如 TeX Live 或 MiKTeX。模板使用 `ctex` 处理中文,并依赖以下宏包:
|
||||||
|
|
||||||
|
```text
|
||||||
|
ctex, geometry, titlesec, titletoc, fancyhdr, listings,
|
||||||
|
xcolor, graphicx, amsmath, amssymb, booktabs, enumitem,
|
||||||
|
tcolorbox, fontawesome5, setspace, hyperref
|
||||||
|
```
|
||||||
|
|
||||||
|
完整安装的 TeX Live 通常已包含这些宏包;使用精简安装时,可能需要通过发行版的包管理器补充安装。
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
1. 复制 `模板/main.tex` 到新的文档目录。
|
||||||
|
2. 修改文件开头“可修改的文档信息”区域:
|
||||||
|
|
||||||
|
```tex
|
||||||
|
\newcommand{\doctitle}{XXXX技术文档}
|
||||||
|
\newcommand{\docsubtitle}{XXXX系统设计与实现}
|
||||||
|
\newcommand{\projectname}{XXXX项目}
|
||||||
|
\newcommand{\docauthor}{XXXX}
|
||||||
|
\newcommand{\docversion}{v1.0}
|
||||||
|
\newcommand{\docdescription}{文档简介}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. 按需修改、复制或删除正文中的示例章节。
|
||||||
|
4. 使用 XeLaTeX 编译两次,以正确生成目录和交叉引用:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
xelatex main.tex
|
||||||
|
xelatex main.tex
|
||||||
|
```
|
||||||
|
|
||||||
|
如果已安装 `latexmk`,也可以使用:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
latexmk -xelatex main.tex
|
||||||
|
```
|
||||||
|
|
||||||
|
5. 编译完成后,在当前目录查看 `main.pdf`。
|
||||||
|
|
||||||
|
## 常用内容
|
||||||
|
|
||||||
|
### 插入图片
|
||||||
|
|
||||||
|
将图片放在 `.tex` 文件所在目录或其子目录中,然后使用:
|
||||||
|
|
||||||
|
```tex
|
||||||
|
\begin{figure}[htbp]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=0.8\linewidth]{images/example.png}
|
||||||
|
\caption{图片说明}
|
||||||
|
\label{fig:example}
|
||||||
|
\end{figure}
|
||||||
|
```
|
||||||
|
|
||||||
|
图片路径相对于当前 `.tex` 文件。复制示例文档时,请同时复制其引用的图片。
|
||||||
|
|
||||||
|
### 插入代码
|
||||||
|
|
||||||
|
模板预设了 `pythonstyle` 和 `bashstyle`:
|
||||||
|
|
||||||
|
```tex
|
||||||
|
\begin{lstlisting}[style=pythonstyle, caption={Python 示例}]
|
||||||
|
def main():
|
||||||
|
print("Hello")
|
||||||
|
\end{lstlisting}
|
||||||
|
```
|
||||||
|
|
||||||
|
将 `style` 改为 `bashstyle` 可展示终端命令。其他语言可以通过 `listings` 的 `language` 参数自行配置。
|
||||||
|
|
||||||
|
### 插入问答框
|
||||||
|
|
||||||
|
```tex
|
||||||
|
\begin{qabox}{这里填写问题}
|
||||||
|
\begin{answerbox}
|
||||||
|
这里填写原因、排查过程和解决方法。
|
||||||
|
\end{answerbox}
|
||||||
|
\end{qabox}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 调整章节
|
||||||
|
|
||||||
|
空白模板目前包含以下内容,可根据实际报告自由删改:
|
||||||
|
|
||||||
|
- 文档概述
|
||||||
|
- 系统设计
|
||||||
|
- 程序文件说明
|
||||||
|
- 关键方法与原理
|
||||||
|
- 实现说明
|
||||||
|
- 测试与结果
|
||||||
|
- 常见问题
|
||||||
|
- 后续规划与版本记录
|
||||||
|
|
||||||
|
## 示例说明
|
||||||
|
|
||||||
|
- `example/停车机器人example`:展示问题描述、原因分析、解决思路、代码片段、公式、测试计划和图片排版。
|
||||||
|
- `example/旧版个人example`:展示篇幅较长的技术报告,包括流程说明、算法原理、表格、双图排版、问答记录和附录。
|
||||||
|
|
||||||
|
两个示例目录均保留了已编译 PDF,可在未安装 LaTeX 环境时先查看最终排版效果。
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
### 中文无法正常显示
|
||||||
|
|
||||||
|
优先确认使用的是 XeLaTeX,而不是直接使用传统 LaTeX 命令;同时确认 TeX 发行版已安装中文支持和 `ctex`。
|
||||||
|
|
||||||
|
### 提示找不到宏包
|
||||||
|
|
||||||
|
根据错误信息,通过 TeX Live 或 MiKTeX 的包管理器安装对应宏包。若缺少图标相关命令,请重点检查 `fontawesome5`。
|
||||||
|
|
||||||
|
### 目录或引用没有更新
|
||||||
|
|
||||||
|
连续编译两次,或使用 `latexmk -xelatex main.tex` 自动处理多轮编译。
|
||||||
|
|
||||||
|
### 图片无法找到
|
||||||
|
|
||||||
|
检查文件名、扩展名和相对路径是否一致。移动或复制示例的 `main.tex` 时,也需要带上它引用的 PNG 文件。
|
||||||
|
|
||||||
|
## 说明
|
||||||
|
|
||||||
|
仓库中未提供许可证文件。使用或分发前,请根据实际归属补充许可证或内部使用说明。
|
||||||
|
|
||||||
+159
@@ -0,0 +1,159 @@
|
|||||||
|
# Technical Report LaTeX Template
|
||||||
|
|
||||||
|
[简体中文](README.md) | [English](README_en.md)
|
||||||
|
|
||||||
|
This repository provides a LaTeX template for Chinese technical reports. It is suitable for documenting project design, implementation details, test results, troubleshooting records, FAQs, and future plans. A blank template and two complete examples are included for direct reuse.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- A4 paper, 12 pt text, 2.5 cm margins, and 1.5 line spacing
|
||||||
|
- Cover page, automatic table of contents, headers, footers, and version information
|
||||||
|
- Preset heading levels, hyperlinks, and color styles
|
||||||
|
- Support for code listings, equations, tables, images, and lists
|
||||||
|
- Reusable file-description and question-and-answer boxes
|
||||||
|
- Preset syntax highlighting for Python and Bash
|
||||||
|
|
||||||
|
## Directory Structure
|
||||||
|
|
||||||
|
```text
|
||||||
|
.
|
||||||
|
├─ 模板/
|
||||||
|
│ ├─ main.tex # Blank template ready for editing
|
||||||
|
│ └─ 模板.pdf # Compiled preview of the template
|
||||||
|
├─ example/
|
||||||
|
│ ├─ 停车机器人example/
|
||||||
|
│ │ ├─ main.tex # Example troubleshooting report
|
||||||
|
│ │ ├─ *.png # Images used by the example
|
||||||
|
│ │ └─ *.pdf # Compiled example document
|
||||||
|
│ └─ 旧版个人example/
|
||||||
|
│ ├─ main.tex # Longer personal technical report example
|
||||||
|
│ ├─ *.png # Images used by the example
|
||||||
|
│ └─ *.pdf # Compiled example document
|
||||||
|
├─ README.md
|
||||||
|
└─ README_en.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
Install a LaTeX distribution that includes XeLaTeX, such as TeX Live or MiKTeX. The template uses `ctex` for Chinese typesetting and depends on the following packages:
|
||||||
|
|
||||||
|
```text
|
||||||
|
ctex, geometry, titlesec, titletoc, fancyhdr, listings,
|
||||||
|
xcolor, graphicx, amsmath, amssymb, booktabs, enumitem,
|
||||||
|
tcolorbox, fontawesome5, setspace, hyperref
|
||||||
|
```
|
||||||
|
|
||||||
|
A full TeX Live installation normally includes these packages. With a minimal installation, use the distribution's package manager to install any missing packages.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
1. Copy `模板/main.tex` to a new document directory.
|
||||||
|
2. Edit the document metadata near the beginning of the file:
|
||||||
|
|
||||||
|
```tex
|
||||||
|
\newcommand{\doctitle}{Technical Document Title}
|
||||||
|
\newcommand{\docsubtitle}{System Design and Implementation}
|
||||||
|
\newcommand{\projectname}{Project Name}
|
||||||
|
\newcommand{\docauthor}{Author}
|
||||||
|
\newcommand{\docversion}{v1.0}
|
||||||
|
\newcommand{\docdescription}{A short document description}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Edit, duplicate, or remove the sample sections as needed.
|
||||||
|
4. Run XeLaTeX twice so that the table of contents and cross-references are updated:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
xelatex main.tex
|
||||||
|
xelatex main.tex
|
||||||
|
```
|
||||||
|
|
||||||
|
If `latexmk` is installed, you can instead run:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
latexmk -xelatex main.tex
|
||||||
|
```
|
||||||
|
|
||||||
|
5. Open `main.pdf` in the current directory.
|
||||||
|
|
||||||
|
## Common Elements
|
||||||
|
|
||||||
|
### Images
|
||||||
|
|
||||||
|
Place images next to the `.tex` file or in a subdirectory, then reference them as follows:
|
||||||
|
|
||||||
|
```tex
|
||||||
|
\begin{figure}[htbp]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=0.8\linewidth]{images/example.png}
|
||||||
|
\caption{Image description}
|
||||||
|
\label{fig:example}
|
||||||
|
\end{figure}
|
||||||
|
```
|
||||||
|
|
||||||
|
Image paths are relative to the current `.tex` file. When copying an example document, copy its referenced images as well.
|
||||||
|
|
||||||
|
### Code Listings
|
||||||
|
|
||||||
|
The template defines `pythonstyle` and `bashstyle`:
|
||||||
|
|
||||||
|
```tex
|
||||||
|
\begin{lstlisting}[style=pythonstyle, caption={Python example}]
|
||||||
|
def main():
|
||||||
|
print("Hello")
|
||||||
|
\end{lstlisting}
|
||||||
|
```
|
||||||
|
|
||||||
|
Change the style to `bashstyle` for terminal commands. Other languages can be configured through the `language` option provided by `listings`.
|
||||||
|
|
||||||
|
### Question-and-Answer Boxes
|
||||||
|
|
||||||
|
```tex
|
||||||
|
\begin{qabox}{Write the question here}
|
||||||
|
\begin{answerbox}
|
||||||
|
Describe the cause, investigation, and solution here.
|
||||||
|
\end{answerbox}
|
||||||
|
\end{qabox}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Report Sections
|
||||||
|
|
||||||
|
The blank template currently includes the following sections, all of which can be edited or removed:
|
||||||
|
|
||||||
|
- Document overview
|
||||||
|
- System design
|
||||||
|
- Program file descriptions
|
||||||
|
- Key methods and principles
|
||||||
|
- Implementation details
|
||||||
|
- Tests and results
|
||||||
|
- Frequently asked questions
|
||||||
|
- Future plans and version history
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
- `example/停车机器人example` demonstrates problem descriptions, root-cause analysis, proposed solutions, code snippets, equations, test plans, and image layout.
|
||||||
|
- `example/旧版个人example` demonstrates a longer technical report with process descriptions, algorithm details, tables, side-by-side images, Q&A records, and appendices.
|
||||||
|
|
||||||
|
Both example directories include compiled PDF files, allowing the final layout to be reviewed without a local LaTeX installation.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Chinese text is not rendered correctly
|
||||||
|
|
||||||
|
Make sure the document is compiled with XeLaTeX rather than the traditional LaTeX command, and verify that Chinese language support and `ctex` are installed.
|
||||||
|
|
||||||
|
### A package cannot be found
|
||||||
|
|
||||||
|
Install the package named in the error through the TeX Live or MiKTeX package manager. If icon commands are missing, check the `fontawesome5` package in particular.
|
||||||
|
|
||||||
|
### The table of contents or references are outdated
|
||||||
|
|
||||||
|
Compile the document twice, or run `latexmk -xelatex main.tex` to handle the required passes automatically.
|
||||||
|
|
||||||
|
### An image cannot be found
|
||||||
|
|
||||||
|
Check the file name, extension, and relative path. When moving or copying an example `main.tex`, include all referenced PNG files.
|
||||||
|
|
||||||
|
## License Note
|
||||||
|
|
||||||
|
No license file is currently included in this repository. Add an appropriate license or an internal-use notice before redistribution.
|
||||||
|
|
||||||
@@ -0,0 +1,374 @@
|
|||||||
|
\documentclass[12pt, a4paper]{article}
|
||||||
|
|
||||||
|
% ========== 基础包 ==========
|
||||||
|
\usepackage[UTF8]{ctex} % 中文支持
|
||||||
|
\usepackage[margin=2.5cm]{geometry} % 页边距
|
||||||
|
\usepackage{titlesec} % 章节标题格式
|
||||||
|
\usepackage{titletoc} % 目录格式
|
||||||
|
\usepackage{fancyhdr} % 页眉页脚
|
||||||
|
\usepackage{listings} % 代码块
|
||||||
|
\usepackage{xcolor} % 颜色
|
||||||
|
\usepackage{graphicx} % 图片
|
||||||
|
\usepackage{amsmath} % 数学公式
|
||||||
|
\usepackage{amssymb} % 数学符号
|
||||||
|
\usepackage{booktabs} % 表格
|
||||||
|
\usepackage{enumitem} % 列表格式
|
||||||
|
\usepackage{tcolorbox} % 彩色盒子
|
||||||
|
\usepackage{fontawesome5} % 图标
|
||||||
|
\usepackage{setspace} % 行距
|
||||||
|
\usepackage{hyperref} % 超链接
|
||||||
|
|
||||||
|
% ========== 页面设置 ==========
|
||||||
|
\onehalfspacing
|
||||||
|
|
||||||
|
% ========== 可修改的文档信息 ==========
|
||||||
|
\newcommand{\doctitle}{停车机器人}
|
||||||
|
\newcommand{\docsubtitle}{坐标变换问题排查与后续计划}
|
||||||
|
\newcommand{\projectname}{停车机器人项目}
|
||||||
|
\newcommand{\docauthor}{沈玉祥}
|
||||||
|
\newcommand{\docversion}{v1.0}
|
||||||
|
\newcommand{\docdescription}{本文档用于说明XXXX项目的设计、实现、测试及维护方法。}
|
||||||
|
|
||||||
|
% ========== 页眉页脚 ==========
|
||||||
|
\pagestyle{fancy}
|
||||||
|
\fancyhf{}
|
||||||
|
\fancyhead[L]{\small \doctitle}
|
||||||
|
\fancyhead[R]{\small \leftmark}
|
||||||
|
\fancyfoot[C]{\thepage}
|
||||||
|
\renewcommand{\headrulewidth}{0.4pt}
|
||||||
|
|
||||||
|
% ========== 颜色设置 ==========
|
||||||
|
\definecolor{codebg}{RGB}{245, 245, 245}
|
||||||
|
\definecolor{codeframe}{RGB}{200, 200, 200}
|
||||||
|
\definecolor{codegreen}{rgb}{0,0.6,0}
|
||||||
|
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
|
||||||
|
\definecolor{codepurple}{rgb}{0.58,0,0.82}
|
||||||
|
|
||||||
|
% ========== 超链接设置 ==========
|
||||||
|
\hypersetup{
|
||||||
|
colorlinks=true,
|
||||||
|
linkcolor=blue!70!black,
|
||||||
|
urlcolor=blue!70!black,
|
||||||
|
citecolor=green!60!black,
|
||||||
|
bookmarks=true,
|
||||||
|
bookmarksnumbered=true,
|
||||||
|
pdftitle={\doctitle},
|
||||||
|
pdfauthor={\docauthor}
|
||||||
|
}
|
||||||
|
|
||||||
|
% ========== 代码块设置 ==========
|
||||||
|
\lstdefinestyle{pythonstyle}{
|
||||||
|
backgroundcolor=\color{codebg},
|
||||||
|
commentstyle=\color{codegreen},
|
||||||
|
keywordstyle=\color{blue}\bfseries,
|
||||||
|
numberstyle=\tiny\color{codegray},
|
||||||
|
stringstyle=\color{codepurple},
|
||||||
|
basicstyle=\ttfamily\footnotesize,
|
||||||
|
breakatwhitespace=false,
|
||||||
|
breaklines=true,
|
||||||
|
captionpos=b,
|
||||||
|
keepspaces=true,
|
||||||
|
numbers=left,
|
||||||
|
numbersep=5pt,
|
||||||
|
showspaces=false,
|
||||||
|
showstringspaces=false,
|
||||||
|
showtabs=false,
|
||||||
|
tabsize=4,
|
||||||
|
frame=single,
|
||||||
|
rulecolor=\color{codeframe},
|
||||||
|
language=Python
|
||||||
|
}
|
||||||
|
|
||||||
|
\lstdefinestyle{bashstyle}{
|
||||||
|
backgroundcolor=\color{codebg},
|
||||||
|
basicstyle=\ttfamily\footnotesize,
|
||||||
|
breaklines=true,
|
||||||
|
frame=single,
|
||||||
|
rulecolor=\color{codeframe},
|
||||||
|
language=bash,
|
||||||
|
commentstyle=\color{codegreen},
|
||||||
|
keywordstyle=\color{blue}
|
||||||
|
}
|
||||||
|
|
||||||
|
\lstset{style=pythonstyle}
|
||||||
|
|
||||||
|
% ========== 彩色盒子样式 ==========
|
||||||
|
\tcbuselibrary{skins, breakable}
|
||||||
|
|
||||||
|
\newtcolorbox{qabox}[2][]{
|
||||||
|
enhanced,
|
||||||
|
breakable,
|
||||||
|
colback=blue!5!white,
|
||||||
|
colframe=blue!60!black,
|
||||||
|
fonttitle=\bfseries,
|
||||||
|
title={Q: #2},
|
||||||
|
#1
|
||||||
|
}
|
||||||
|
|
||||||
|
\newtcolorbox{answerbox}[1][]{
|
||||||
|
enhanced,
|
||||||
|
breakable,
|
||||||
|
colback=green!5!white,
|
||||||
|
colframe=green!60!black,
|
||||||
|
leftrule=4pt,
|
||||||
|
#1
|
||||||
|
}
|
||||||
|
|
||||||
|
\newtcolorbox{filebox}[2][]{
|
||||||
|
enhanced,
|
||||||
|
breakable,
|
||||||
|
colback=gray!10!white,
|
||||||
|
colframe=gray!60!black,
|
||||||
|
fonttitle=\bfseries\ttfamily,
|
||||||
|
title={\faFile\ #2},
|
||||||
|
#1
|
||||||
|
}
|
||||||
|
|
||||||
|
% ========== 章节标题格式 ==========
|
||||||
|
\titleformat{\section}
|
||||||
|
{\Large\bfseries\color{blue!70!black}}
|
||||||
|
{\thesection}{1em}{}
|
||||||
|
[\titlerule]
|
||||||
|
|
||||||
|
\titleformat{\subsection}
|
||||||
|
{\large\bfseries\color{blue!50!black}}
|
||||||
|
{\thesubsection}{1em}{}
|
||||||
|
|
||||||
|
\titleformat{\subsubsection}
|
||||||
|
{\normalsize\bfseries}
|
||||||
|
{\thesubsubsection}{1em}{}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
|
||||||
|
% ========== 封面 ==========
|
||||||
|
\begin{titlepage}
|
||||||
|
\centering
|
||||||
|
\vspace*{3cm}
|
||||||
|
|
||||||
|
{\Huge\bfseries \doctitle\\[0.5em]
|
||||||
|
\Large \docsubtitle}
|
||||||
|
|
||||||
|
\vspace{2cm}
|
||||||
|
\rule{\linewidth}{0.5mm}
|
||||||
|
\vspace{1cm}
|
||||||
|
|
||||||
|
{\large
|
||||||
|
\begin{tabular}{ll}
|
||||||
|
\textbf{项目名称:} & \projectname \\[0.5em]
|
||||||
|
\textbf{作者:} & \docauthor \\[0.5em]
|
||||||
|
\textbf{日期:} & \today \\[0.5em]
|
||||||
|
\textbf{版本:} & \docversion \\
|
||||||
|
\end{tabular}
|
||||||
|
}
|
||||||
|
|
||||||
|
\vspace{1cm}
|
||||||
|
\rule{\linewidth}{0.5mm}
|
||||||
|
|
||||||
|
\vfill
|
||||||
|
{\small \docdescription}
|
||||||
|
\end{titlepage}
|
||||||
|
|
||||||
|
% ========== 目录 ==========
|
||||||
|
\tableofcontents
|
||||||
|
\newpage
|
||||||
|
|
||||||
|
% ============================================================
|
||||||
|
% 使用时可直接修改下面各章节,也可以复制或删除任意示例
|
||||||
|
% ============================================================
|
||||||
|
\section{文档概述}
|
||||||
|
|
||||||
|
\subsection{编写目的}
|
||||||
|
本文档主要针对停车机器人坐标变换的问题排查以及后续规划安排的说明。
|
||||||
|
|
||||||
|
\subsection{项目位置}
|
||||||
|
XXXX:git链接以及分支
|
||||||
|
|
||||||
|
\subsection{已知问题}
|
||||||
|
|
||||||
|
\begin{enumerate}
|
||||||
|
\item 坐标系变换问题bug
|
||||||
|
\item ±120°物理限制无反馈方式
|
||||||
|
\item Simple设置初次设置任务需要等待较长时间
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
% \subsection{术语说明}
|
||||||
|
% \begin{table}[htbp]
|
||||||
|
% \centering
|
||||||
|
% \caption{术语说明示例}
|
||||||
|
% \begin{tabular}{ll}
|
||||||
|
% \toprule
|
||||||
|
% \textbf{术语} & \textbf{说明} \\
|
||||||
|
% \midrule
|
||||||
|
% XXXX & 填写术语的完整名称及含义 \\
|
||||||
|
% XXXX & 填写缩写、单位或专有概念 \\
|
||||||
|
% \bottomrule
|
||||||
|
% \end{tabular}
|
||||||
|
% \end{table}
|
||||||
|
|
||||||
|
\section{蟹行反向}
|
||||||
|
|
||||||
|
\subsection{问题描述}
|
||||||
|
蟹行模式发送正速度理论来说应往车体左侧运动,实际向车体右侧运动,这个不一致的问题
|
||||||
|
|
||||||
|
\subsection{问题原因}
|
||||||
|
SetChassisDirection(90) 的含义容易误解,它设置的“车身坐标系相对运动坐标系的偏置” +90°,不是让舵轮转到 +90°。
|
||||||
|
\begin{lstlisting}[caption={蟹行反向原因梳理}]
|
||||||
|
右摇杆Y > 0
|
||||||
|
→ speed > 0
|
||||||
|
→ SetChassisDirection(+90°)
|
||||||
|
→ 舵轮零方向 ZeroDirection = +90°
|
||||||
|
→ SendMotion 的直行轴角 axisTh = 0°
|
||||||
|
→ 实际舵角目标 = axisTh - ZeroDirection
|
||||||
|
→ 0° - 90° = -90°
|
||||||
|
→ 正速度沿 -90° 方向运动
|
||||||
|
→ 整车向右蟹行
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
\subsection{解决思路}
|
||||||
|
增加类似ROS的TF变换的简化版本,暂时不对commonusage上层进行改动,针对停车机器人本项目增加适配层,明确语义,方便后续多车编队坐标系问题的排查。
|
||||||
|
\begin{lstlisting}[caption={目前解决思路梳理}]
|
||||||
|
MyParking
|
||||||
|
├─ Shared
|
||||||
|
│ ├─ FrameTransform2D.cs 坐标变换
|
||||||
|
│ ├─ ChassisCommand.cs Pose2D、Twist2D等数据定义
|
||||||
|
│ ├─ FleetKinematics.cs 车队到各单车的运动学分解
|
||||||
|
│ └─ MultiWheelChassisAdapter.cs 包装原Chassis
|
||||||
|
├─ MedullaAdapter
|
||||||
|
└─ ClumsyPilot
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
|
||||||
|
\section{CommonUsage问题}
|
||||||
|
\subsection{问题整理}
|
||||||
|
|
||||||
|
\subsubsection{\texttt{SendXYThSpeed()}}
|
||||||
|
|
||||||
|
使用 $F$ 坐标系下的 \texttt{sw.Position} 计算角度,却直接作为 $B$ 坐标系舵角下发,未减去 \texttt{sw.ZeroDirection}。因此非零偏置下存在坐标系混用风险。
|
||||||
|
|
||||||
|
\subsubsection{\texttt{GetCarSpeed()}}
|
||||||
|
|
||||||
|
使用 $F$ 坐标系下的轮子位置,与 $B$ 坐标系下的舵角共同计算速度。非零偏置下,得到的 $V_x/V_y$ 坐标系不明确。
|
||||||
|
|
||||||
|
\subsubsection{差速舵左右轮位置计算}
|
||||||
|
|
||||||
|
\texttt{AccumulateSpeed()} 使用 $F$ 坐标系下的 \texttt{dsw.Position},但轮子方向 \texttt{\_sendAngle[i]} 属于 $B$ 坐标系。应转换为:
|
||||||
|
|
||||||
|
\[
|
||||||
|
\texttt{wheelDirInFleet}
|
||||||
|
=
|
||||||
|
\texttt{\_sendAngle[i]}
|
||||||
|
+
|
||||||
|
\texttt{dsw.ZeroDirection}
|
||||||
|
\]
|
||||||
|
|
||||||
|
\subsubsection{\texttt{SendRotateMotion()}}
|
||||||
|
|
||||||
|
目标舵角使用 \texttt{sw.Position} 计算正确,但旋转半径使用了相对单车中心的 \texttt{CenterDistance()}。当编队原点存在位置偏置时,应改为:
|
||||||
|
|
||||||
|
\[
|
||||||
|
\texttt{sw.Position.Length()}
|
||||||
|
\]
|
||||||
|
|
||||||
|
\subsubsection{\texttt{CommonMath} 角度归一化}
|
||||||
|
|
||||||
|
当前使用以下方式进行角度归一化:
|
||||||
|
|
||||||
|
\begin{lstlisting}[language={[Sharp]C}]
|
||||||
|
angle - Math.Round(angle / 360f) * 360f
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
受 \texttt{Math.Round()} 银行家舍入影响,在 $\pm180^\circ$、$\pm540^\circ$ 等边界处可能同时出现 $180^\circ$ 和 $-180^\circ$ 两种表达。虽然物理含义相同,但容易影响范围判断,建议统一归一化到:
|
||||||
|
|
||||||
|
\[
|
||||||
|
[-180^\circ,\,180^\circ)
|
||||||
|
\]
|
||||||
|
|
||||||
|
\subsection{总体结论}
|
||||||
|
|
||||||
|
CommonUsage 的核心坐标变换公式基本正确,主要问题是接口没有明确规定输入输出属于车体坐标系 $B$、编队坐标系 $F$ 还是世界坐标系 $W$。
|
||||||
|
|
||||||
|
例如,\texttt{CommonMath.Transform2D(src, t)} 无法从方法名判断输入输出的坐标系、变换方向及数据类型。当前系统也缺少
|
||||||
|
\texttt{BodyFrame}、\texttt{FleetFrame}、\texttt{WorldFrame} 等坐标系定义,
|
||||||
|
\texttt{Pose2D}、\texttt{Twist2D} 等明确类型,以及
|
||||||
|
\texttt{BodyToFleet()}、\texttt{FleetToBody()} 等方向性接口。
|
||||||
|
|
||||||
|
因此,CommonUsage 具备坐标变换的数学工具,但缺少坐标变换的语义管理层。当 \texttt{originBias} 不为零时,\texttt{SendXYThSpeed()}、\texttt{GetCarSpeed()}、差速舵轮速计算及 \texttt{SendRotateMotion()} 存在坐标系混用或旋转半径不明确的问题。
|
||||||
|
|
||||||
|
更准确地说:核心变换思路正确,但接口契约不清晰,部分方法仅在
|
||||||
|
\texttt{originBias = 0} 时能够明确保证坐标一致。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\section{测试实验}
|
||||||
|
|
||||||
|
\subsection{当前进度}
|
||||||
|
|
||||||
|
目前已完成停车机器人M层和C层代码的整理、编译及部署,并通过实车验证。车辆现已能够正常完成前进、后退、蟹行和原地旋转等基本动作,C层、M层到底层电机的控制链路已经打通。
|
||||||
|
|
||||||
|
\subsection{后续计划}
|
||||||
|
|
||||||
|
下一阶段将针对直线、圆弧和贝塞尔曲线开展重复性实车测试。从底盘读取实际速度反馈,从Detour读取车辆实际运动轨迹,并使用Python脚本量化现有方法的轨迹跟踪精度和速度响应,绘制参考值与实际值的对比曲线。
|
||||||
|
|
||||||
|
在此基础上建立车辆运动学模型,设计基于LQR的Track轨迹跟踪方法,并研究舵轮$\pm120^\circ$物理约束下的运动控制和指令分解。首先完成单车轨迹跟踪测试与优化,待单车控制稳定后,再开展双车及多车协调控制研究。简要后续规划整理如下:
|
||||||
|
|
||||||
|
\begin{lstlisting}[caption={后续计划简要梳理}]
|
||||||
|
一、定义实验需要获取的物理量:车的速度反馈、位置信息
|
||||||
|
二、速度信息从M层可获取、位置信息计划从Detour中获得
|
||||||
|
三、后续主要先测多种的直线、圆弧和贝塞尔曲线、多次实验
|
||||||
|
四、获取下发速度、实际速度、理论轨迹、实际轨迹后用python脚本画出曲线;
|
||||||
|
观察跟踪精度、横向偏差、纵向偏差、速度响应等量化指标
|
||||||
|
五、测量当前stanley控制器的量化跟踪的性能、编写LQR控制器
|
||||||
|
六、单车跑通跑稳之后增加±120°极限位置的打印/停车调整的防御策略,设置极限位置进行测试
|
||||||
|
七、单车调整过程中排查一些已知的bug,假如新写的适配层功能不足,可能会考虑修改commonusage的Chassis的部分代码
|
||||||
|
八、当单车调稳之后、编写双车之间的通信和调整方法,仿真验证坐标系转换是否正常再实车试验
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
% \begin{enumerate}
|
||||||
|
% \item XXXX:填写流程的第一步。
|
||||||
|
% \item XXXX:填写流程的第二步。
|
||||||
|
% \item XXXX:填写流程的第三步。
|
||||||
|
% \end{enumerate}
|
||||||
|
|
||||||
|
\section{库版本不一致问题}
|
||||||
|
如图~\ref{fig:example}~所示,停车机器人仓库自带的ref的commonusage.dll会比仓库里commonusage的项目多一些方法,应该是之前排除问题的时候也对上层的commonusage进行了修改,有版本不一致的问题。
|
||||||
|
\begin{figure}[htbp]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=\linewidth]{pic.png}
|
||||||
|
\caption{问题描述}
|
||||||
|
\label{fig:example}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\section{后续规划}
|
||||||
|
|
||||||
|
\subsection{个人想法}
|
||||||
|
\subsubsection{项目引用和版本问题}
|
||||||
|
目前的仓库项目的.csproj文件大多对dll的引用是通过绝对路径,建议使用相对路径自带一个ref文件夹来包含项目需要的依赖,同时需要确认依赖的版本一致。
|
||||||
|
\subsubsection{readme问题}
|
||||||
|
项目增加readme说明,固定格式,可通过简单的skill执行;同时一些实际执行遇到的问题可以记录成文件放在项目里面,方便学习和后续使用。
|
||||||
|
\subsubsection{技术文档}
|
||||||
|
技术文档的固定模板,有时候语言表达问题不全面,需要文档进行记录或者整理。
|
||||||
|
\subsection{版本记录}
|
||||||
|
\begin{table}[htbp]
|
||||||
|
\centering
|
||||||
|
\caption{版本记录}
|
||||||
|
\begin{tabular}{llll}
|
||||||
|
\toprule
|
||||||
|
\textbf{版本} & \textbf{日期} & \textbf{作者} & \textbf{修改内容} \\
|
||||||
|
\midrule
|
||||||
|
v1.0 & \today & 沈玉祥 & 创建基础文档 \\
|
||||||
|
\bottomrule
|
||||||
|
\end{tabular}
|
||||||
|
\end{table}
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
|
||||||
|
\section{时间计划节点}
|
||||||
|
\begin{figure}[htbp]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=\linewidth]{parking.png}
|
||||||
|
\caption{停车机器人节点计划}
|
||||||
|
\label{fig:parking}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
|
||||||
|
\end{document}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 482 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 127 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 120 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 143 KiB |
@@ -0,0 +1,875 @@
|
|||||||
|
\documentclass[12pt, a4paper]{article}
|
||||||
|
|
||||||
|
% ========== 基础包 ==========
|
||||||
|
\usepackage[UTF8]{ctex} % 中文支持
|
||||||
|
\usepackage[margin=2.5cm]{geometry} % 页边距
|
||||||
|
\usepackage{titlesec} % 章节标题格式
|
||||||
|
\usepackage{titletoc} % 目录格式
|
||||||
|
\usepackage{fancyhdr} % 页眉页脚
|
||||||
|
\usepackage{listings} % 代码块
|
||||||
|
\usepackage{xcolor} % 颜色
|
||||||
|
\usepackage{graphicx} % 图片
|
||||||
|
\usepackage{amsmath} % 数学公式
|
||||||
|
\usepackage{amssymb} % 数学符号
|
||||||
|
\usepackage{booktabs} % 表格
|
||||||
|
\usepackage{enumitem} % 列表格式
|
||||||
|
\usepackage{tcolorbox} % 彩色盒子(用于Q&A)
|
||||||
|
\usepackage{fontawesome5} % 图标
|
||||||
|
\usepackage{setspace} % 行距
|
||||||
|
\usepackage{hyperref} % 超链接(放最后避免与其他包冲突)
|
||||||
|
\lstdefinestyle{bashstyle}{
|
||||||
|
backgroundcolor=\color{codebg},
|
||||||
|
basicstyle=\ttfamily\footnotesize,
|
||||||
|
breaklines=true,
|
||||||
|
frame=single,
|
||||||
|
rulecolor=\color{codeframe},
|
||||||
|
language=bash,
|
||||||
|
commentstyle=\color{codegreen},
|
||||||
|
keywordstyle=\color{blue},
|
||||||
|
}
|
||||||
|
% ========== 页面设置 ==========
|
||||||
|
\onehalfspacing % 1.5倍行距
|
||||||
|
|
||||||
|
% ========== 页眉页脚 ==========
|
||||||
|
\pagestyle{fancy}
|
||||||
|
\fancyhf{}
|
||||||
|
\fancyhead[L]{\small 机器人动作重定向文档}
|
||||||
|
\fancyhead[R]{\small \leftmark}
|
||||||
|
\fancyfoot[C]{\thepage}
|
||||||
|
\renewcommand{\headrulewidth}{0.4pt}
|
||||||
|
|
||||||
|
% ========== 超链接设置 ==========
|
||||||
|
\hypersetup{
|
||||||
|
colorlinks=true,
|
||||||
|
linkcolor=blue!70!black,
|
||||||
|
urlcolor=blue!70!black,
|
||||||
|
citecolor=green!60!black,
|
||||||
|
bookmarks=true,
|
||||||
|
bookmarksnumbered=true
|
||||||
|
}
|
||||||
|
|
||||||
|
% ========== 代码块设置 ==========
|
||||||
|
\definecolor{codebg}{RGB}{245, 245, 245}
|
||||||
|
\definecolor{codeframe}{RGB}{200, 200, 200}
|
||||||
|
\definecolor{codegreen}{rgb}{0,0.6,0}
|
||||||
|
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
|
||||||
|
\definecolor{codepurple}{rgb}{0.58,0,0.82}
|
||||||
|
|
||||||
|
\lstdefinestyle{pythonstyle}{
|
||||||
|
backgroundcolor=\color{codebg},
|
||||||
|
commentstyle=\color{codegreen},
|
||||||
|
keywordstyle=\color{blue}\bfseries,
|
||||||
|
numberstyle=\tiny\color{codegray},
|
||||||
|
stringstyle=\color{codepurple},
|
||||||
|
basicstyle=\ttfamily\footnotesize,
|
||||||
|
breakatwhitespace=false,
|
||||||
|
breaklines=true,
|
||||||
|
captionpos=b,
|
||||||
|
keepspaces=true,
|
||||||
|
numbers=left,
|
||||||
|
numbersep=5pt,
|
||||||
|
showspaces=false,
|
||||||
|
showstringspaces=false,
|
||||||
|
showtabs=false,
|
||||||
|
tabsize=4,
|
||||||
|
frame=single,
|
||||||
|
rulecolor=\color{codeframe},
|
||||||
|
language=Python
|
||||||
|
}
|
||||||
|
|
||||||
|
\lstset{style=pythonstyle}
|
||||||
|
|
||||||
|
% ========== Q&A 盒子样式 ==========
|
||||||
|
\tcbuselibrary{skins, breakable}
|
||||||
|
|
||||||
|
\newtcolorbox{qabox}[2][]{
|
||||||
|
enhanced,
|
||||||
|
breakable,
|
||||||
|
colback=blue!5!white,
|
||||||
|
colframe=blue!60!black,
|
||||||
|
fonttitle=\bfseries,
|
||||||
|
title={Q: #2},
|
||||||
|
#1
|
||||||
|
}
|
||||||
|
|
||||||
|
\newtcolorbox{answerbox}[1][]{
|
||||||
|
enhanced,
|
||||||
|
breakable,
|
||||||
|
colback=green!5!white,
|
||||||
|
colframe=green!60!black,
|
||||||
|
leftrule=4pt,
|
||||||
|
#1
|
||||||
|
}
|
||||||
|
|
||||||
|
% ========== 文件说明盒子 ==========
|
||||||
|
\newtcolorbox{filebox}[2][]{
|
||||||
|
enhanced,
|
||||||
|
breakable,
|
||||||
|
colback=gray!10!white,
|
||||||
|
colframe=gray!60!black,
|
||||||
|
fonttitle=\bfseries\ttfamily,
|
||||||
|
title={\faFile\ #2},
|
||||||
|
#1
|
||||||
|
}
|
||||||
|
|
||||||
|
% ========== 章节标题格式 ==========
|
||||||
|
\titleformat{\section}
|
||||||
|
{\Large\bfseries\color{blue!70!black}}
|
||||||
|
{\thesection}{1em}{}
|
||||||
|
[\titlerule]
|
||||||
|
|
||||||
|
\titleformat{\subsection}
|
||||||
|
{\large\bfseries\color{blue!50!black}}
|
||||||
|
{\thesubsection}{1em}{}
|
||||||
|
|
||||||
|
\titleformat{\subsubsection}
|
||||||
|
{\normalsize\bfseries}
|
||||||
|
{\thesubsubsection}{1em}{}
|
||||||
|
|
||||||
|
% ========== 文档开始 ==========
|
||||||
|
\begin{document}
|
||||||
|
|
||||||
|
% ========== 封面 ==========
|
||||||
|
\begin{titlepage}
|
||||||
|
\centering
|
||||||
|
\vspace*{3cm}
|
||||||
|
|
||||||
|
{\Huge\bfseries 机器人动作重定向\\[0.5em]
|
||||||
|
\Large 技术文档}
|
||||||
|
|
||||||
|
\vspace{2cm}
|
||||||
|
\rule{\linewidth}{0.5mm}
|
||||||
|
\vspace{1cm}
|
||||||
|
|
||||||
|
{\large
|
||||||
|
\begin{tabular}{ll}
|
||||||
|
\textbf{项目名称:} & 人形机器人动作重定向系统 \\[0.5em]
|
||||||
|
\textbf{作者:} & 沈玉祥 \\[0.5em]
|
||||||
|
\textbf{日期:} & \today \\[0.5em]
|
||||||
|
\textbf{版本:} & v1.0 \\
|
||||||
|
\end{tabular}
|
||||||
|
}
|
||||||
|
|
||||||
|
\vspace{1cm}
|
||||||
|
\rule{\linewidth}{0.5mm}
|
||||||
|
|
||||||
|
\vfill
|
||||||
|
{\small 本文档记录了基于PINK差分IK的人形机器人动作重定向方法及实现细节}
|
||||||
|
\end{titlepage}
|
||||||
|
|
||||||
|
% ========== 目录 ==========
|
||||||
|
\tableofcontents
|
||||||
|
\newpage
|
||||||
|
|
||||||
|
% ============================================================
|
||||||
|
% 第一章:程序文件说明
|
||||||
|
% ============================================================
|
||||||
|
\section{程序文件说明}
|
||||||
|
|
||||||
|
\subsection{概述}
|
||||||
|
主要包括:人体动作到机器人动作的重定向方法、动作之间的平滑插值、视频提取到机器人动作的方法等内容。
|
||||||
|
% 在这里写一段整体项目结构的介绍
|
||||||
|
|
||||||
|
\subsection{核心文件}
|
||||||
|
|
||||||
|
% ---- 文件1 ----
|
||||||
|
\begin{filebox}{\texttt{ik\_redirection\_npy.py}}
|
||||||
|
\textbf{功能:} 将人体动作信息转化为机器人各关节角度(rad)信息。\\[0.5em]
|
||||||
|
\textbf{主要类/函数:}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{H1Config} —— 机器人配置信息
|
||||||
|
\item \texttt{H1PinkSolver} —— 核心求解器
|
||||||
|
\item \texttt{process\_motion()} —— 主处理函数
|
||||||
|
\item \texttt{apply\_bone\_retargeting\_single()} —— 单帧骨骼重定向
|
||||||
|
\item \texttt{load\_data\_all\_npy()} —— 输入格式转换:$[N, 22, 3, T]$ -> 第 i 个 $[T, 22, 3]$
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\vspace{0.5em}
|
||||||
|
\textbf{输入:} $[N, 22, 3]$ 的numpy数组,N为帧数,22为SMPL主要关节数,3为XYZ坐标
|
||||||
|
|
||||||
|
\textbf{输出:} 字典,主要为dof(关节角度序列,弧度,shape为 $[N, 28]$)
|
||||||
|
|
||||||
|
\textbf{运行效率:}0.08s/196帧 $\approx$ 0.4ms/帧(单线程,CPU)
|
||||||
|
\end{filebox}
|
||||||
|
|
||||||
|
\vspace{1em}
|
||||||
|
|
||||||
|
% ---- 文件2 ----
|
||||||
|
\begin{filebox}{\texttt{easy\_MotionInterpolator.py}}
|
||||||
|
\textbf{功能:} 实现机器人动作(关节角度dof)的插值、帧率重定向及平滑处理;可处理过渡的自碰撞问题。
|
||||||
|
|
||||||
|
\vspace{0.5em}
|
||||||
|
\textbf{主要配置项:}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{MotionInterpolator} —— 核心插值类
|
||||||
|
\item \texttt{interpolate()} —— 对dof序列进行三次样条插值
|
||||||
|
\item \texttt{smooth()} —— 加权滑动滤波消除插值引入的抖动
|
||||||
|
\item \texttt{process()} —— 依次执行插值与平滑,返回处理后的dof序列
|
||||||
|
\end{itemize}
|
||||||
|
\vspace{0.5em}
|
||||||
|
\textbf{输入:} 低帧率的关节角度序列,shape为 $[N, 28]$
|
||||||
|
|
||||||
|
\textbf{输出:} 高帧率平滑后的关节角度序列,shape为 $[N', 28]$
|
||||||
|
|
||||||
|
\textbf{运行效率:}单次拼接(含碰撞检测)$\approx$
|
||||||
|
0.8ms(单线程,CPU)
|
||||||
|
\end{filebox}
|
||||||
|
|
||||||
|
\vspace{1em}
|
||||||
|
|
||||||
|
\begin{filebox}{\texttt{vis.py}}
|
||||||
|
\textbf{功能:} 逐帧播放并可视化。
|
||||||
|
|
||||||
|
\vspace{0.5em}
|
||||||
|
\textbf{主要配置项:}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{load\_motion\_data()} —— 加载动作数据
|
||||||
|
\item \texttt{build\_obstacle\_geoms()} —— 根据障碍物数据构建红色线框盒几何体
|
||||||
|
\item \texttt{main()} —— 逐帧绘制机器人关节角度与根节点状态
|
||||||
|
\end{itemize}
|
||||||
|
\vspace{0.5em}
|
||||||
|
\textbf{输入:} 包含dof序列、根节点位姿、可选的h1\_joint\_pos和smpl\_joints\_target
|
||||||
|
|
||||||
|
\textbf{输出:} Isaac Gym实时可视化窗口
|
||||||
|
|
||||||
|
\textbf{依赖:}Isaac Gym、PyTorch(支持GPU加速渲染)
|
||||||
|
\end{filebox}
|
||||||
|
|
||||||
|
% ---- 添加更多文件 ----
|
||||||
|
% \begin{filebox}{\texttt{文件名.py}}
|
||||||
|
% ...
|
||||||
|
% \end{filebox}
|
||||||
|
|
||||||
|
\subsection{服务器端文件}
|
||||||
|
\textbf{位置:} 服务器下的GVHMR目录下;conda activate gvhmr
|
||||||
|
|
||||||
|
\begin{filebox}{\texttt{GVHMR/run.py}}
|
||||||
|
\textbf{功能:} 把人体动作视频(mp4)转换成机器人各关节电机角度(rad)。
|
||||||
|
|
||||||
|
\vspace{0.5em}
|
||||||
|
\textbf{主要配置项:}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{GVHMRSystem} —— 核心系统类
|
||||||
|
\item \texttt{\_\_init\_\_()} —— 冷启动初始化,加载GVHMR主模型、Tracker、VitPose、特征提取器、SMPL模型及H1PinkSolver
|
||||||
|
\item \texttt{process\_video()} —— 热运行入口,处理单个视频,依次执行预处理、GVHMR推理、H1 IK优化,返回关节角度结果
|
||||||
|
\item \texttt{\_run\_preprocess\_efficient()} —— SLAM后台线程并行,Tracker、VitPose、特征提取串行GPU推理
|
||||||
|
\item \texttt{\_run\_h1\_optimization()} —— 从GVHMR输出的SMPL参数提取关节坐标,调用H1PinkSolver完成重定向
|
||||||
|
\end{itemize}
|
||||||
|
\vspace{0.5em}
|
||||||
|
\textbf{输入:} mp4视频文件
|
||||||
|
|
||||||
|
\textbf{输出:} 包含dof关节角度序列(rad,shape为$[N,28]$)的字典
|
||||||
|
|
||||||
|
\textbf{使用方法:}
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
conda activate gvhmr
|
||||||
|
cd GVHMR/
|
||||||
|
python run.py --input (视频路径)
|
||||||
|
# 结果存储到 outputs 目录的 result.pkl 文件
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
\textbf{运行效率:}4.5s/8s(4090GPU)
|
||||||
|
\end{filebox}
|
||||||
|
|
||||||
|
\vspace{1em}
|
||||||
|
|
||||||
|
\begin{filebox}{\texttt{GVHMR/new-server.py}}
|
||||||
|
\textbf{功能:} 支持大模型工具调用的服务端。
|
||||||
|
|
||||||
|
\vspace{0.5em}
|
||||||
|
\textbf{主要配置项:}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{\_run\_gvhmr()} —— 核心推理函数
|
||||||
|
\item \texttt{\_frames\_to\_tmp\_video()} —— 将帧列表写入临时视频文件
|
||||||
|
\item \texttt{\_process\_frames\_async()} —— 异步推理包装
|
||||||
|
\end{itemize}
|
||||||
|
\vspace{0.5em}
|
||||||
|
|
||||||
|
\textbf{主要接口:}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \lstinline{GET /tools} —— 查询当前可用工具,大模型调用前先请求:
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
curl http://localhost:8003/tools\end{lstlisting}
|
||||||
|
\item \lstinline{POST /tool/call} —— 大模型调用工具的入口,传工具名和参数:
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
curl -X POST http://localhost:8003/tool/call \
|
||||||
|
-d '{"name": "process_video_to_robot_motion",
|
||||||
|
"parameters": {"video_path": "/data/demo.mp4"}}'\end{lstlisting}
|
||||||
|
\item \lstinline{POST /generate} —— 直接输入视频文件路径处理:
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
curl -X POST http://localhost:8003/generate \
|
||||||
|
-d '{"video_path": "/data/demo.mp4"}'\end{lstlisting}
|
||||||
|
\item \lstinline{WS /ws/stream} —— 接入实时相机推流,配合 camera\_client.py 使用:
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
python camera_client.py --camera 0\end{lstlisting}
|
||||||
|
\end{itemize}
|
||||||
|
\vspace{0.5em}
|
||||||
|
\textbf{输入:} 视频文件绝对路径,或通过 WebSocket 推送的 JPEG 编码帧字节流
|
||||||
|
|
||||||
|
\textbf{输出:} 字典,主要为 dof(关节角度序列,弧度,shape 为 $[N,28]$)、fps、duration\_sec
|
||||||
|
\end{filebox}
|
||||||
|
|
||||||
|
\vspace{1em}
|
||||||
|
|
||||||
|
\begin{filebox}{\texttt{GVHMR/camera\_client.py}}
|
||||||
|
\textbf{功能:} 获取本地摄像头,将视频帧实时推送到 new-server.py 进行推理,并接收返回的关节角度。\\[0.5em]
|
||||||
|
\textbf{主要函数:}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{run\_camera\_stream()} —— 打开摄像头、推帧、接收结果
|
||||||
|
\item \texttt{\_handle\_result()} —— 处理每次推理返回的结果
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\vspace{0.5em}
|
||||||
|
\textbf{使用方法:}
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
# 默认摄像头,默认参数
|
||||||
|
python camera_client.py
|
||||||
|
|
||||||
|
# 指定摄像头编号
|
||||||
|
python camera_client.py --camera 0 --fps 30 --chunk_sec 4
|
||||||
|
|
||||||
|
# 服务端不在同一台机器时指定地址
|
||||||
|
python camera_client.py --server 192.168.1.100:8003
|
||||||
|
|
||||||
|
# 固定机位相机
|
||||||
|
python camera_client.py --static_cam
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
\textbf{输入:} 本地摄像头实时画面(通过 OpenCV 读取)\\[0.5em]
|
||||||
|
\textbf{输出:} 每隔 \texttt{chunk\_sec} 秒打印一次推理结果,格式如下:
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
[推理结果] chunk_id=0 | 帧数=120 | 时长=4.0s | fps=90 | DOF shape=[360, 28]
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
\textbf{备注:} \texttt{\_handle\_result()} 函数内的注释处(第~117~行)可对接机器人控制器,将 DOF 数据发给 ROS 节点。
|
||||||
|
\end{filebox}
|
||||||
|
|
||||||
|
\vspace{1em}
|
||||||
|
|
||||||
|
\begin{filebox}{\texttt{GVHMR/test\_stream.py}}
|
||||||
|
\textbf{功能:} 用本地 mp4 视频文件模拟摄像头推流,测试 new-server.py 的视频流接口是否正常工作。\\[0.5em]
|
||||||
|
\textbf{主要函数:}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{test\_stream()} —— 读取视频文件逐帧推送到服务端,并接收推理结果
|
||||||
|
\item \texttt{\_print\_result()} —— 打印每个 chunk 的推理结果
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\vspace{0.5em}
|
||||||
|
\textbf{使用方法:}
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
# 基本用法(必须指定视频文件)
|
||||||
|
python test_stream.py --video /data/demo.mp4
|
||||||
|
|
||||||
|
# 指定参数
|
||||||
|
python test_stream.py --video /data/demo.mp4 --fps 30 --chunk_sec 4
|
||||||
|
|
||||||
|
# 服务端不在同一台机器时指定地址
|
||||||
|
python test_stream.py --video /data/demo.mp4 --server 192.168.1.100:8003
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
\textbf{输入:} 本地视频文件路径\\[0.5em]
|
||||||
|
\textbf{输出:} 每积累 \texttt{chunk\_sec} 秒的帧触发一次推理,打印结果:
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
[chunk 0] dof_shape=[360, 28], fps=90, duration=4.0s
|
||||||
|
[done] 共处理 2 个 chunk
|
||||||
|
\end{lstlisting}
|
||||||
|
\end{filebox}
|
||||||
|
|
||||||
|
\subsection{其他说明}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{根节点固定:} 本模块的目标是从人体动作生成机器人电机角度序列,机器人waist点在世界坐标系中保持固定,相当于将机器人腰部悬挂于空间中。根节点的全局位移不参与重定向计算。
|
||||||
|
|
||||||
|
\item \textbf{输出崩溃排查:} 若输出的电机角度出现突变或崩溃,大概率是输入动作幅度过大,超出机器人关节限位范围,导致IK无法在单帧内追上目标。解决方法是适当降低大模型生成的动作幅度,或延长动作时长使运动更平缓。
|
||||||
|
|
||||||
|
\item \textbf{体型通用性:} 重定向模块对输入人体的臂长、身高、体型无要求,骨骼重定向阶段会自动将SMPL骨骼方向映射到机器人实际骨骼长度,不受输入人体比例影响。
|
||||||
|
\end{itemize}
|
||||||
|
% 在这里描述其他辅助脚本
|
||||||
|
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
|
||||||
|
% ============================================================
|
||||||
|
% 第二章:重定向方法与原理
|
||||||
|
% ============================================================
|
||||||
|
\section{重定向方法与原理}
|
||||||
|
\subsection{常见的三种重定向方法}
|
||||||
|
常见的机器人动作重定向方法主要分为三类:梯度下降方法、神经网络模型+IK微调、纯IK逆解方法三种。
|
||||||
|
|
||||||
|
\begin{table}[h]
|
||||||
|
\centering
|
||||||
|
\caption{三种重定向方法对比}
|
||||||
|
\begin{tabular}{p{2.5cm}p{4cm}p{4cm}p{3cm}}
|
||||||
|
\toprule
|
||||||
|
\textbf{方法} & \textbf{优点} & \textbf{缺点} & \textbf{适用场合} \\
|
||||||
|
\midrule
|
||||||
|
梯度下降 &
|
||||||
|
动作质量高;批量处理性价比好 &
|
||||||
|
实时性差,处理数秒视频需2s以上;需预先标定缩放比例 &
|
||||||
|
离线批量处理 \\
|
||||||
|
\midrule
|
||||||
|
神经网络 + IK微调 &
|
||||||
|
推理速度快;兼顾数据驱动与几何约束 &
|
||||||
|
依赖大量高质量标注数据,准备成本高;对体型变化鲁棒性弱 &
|
||||||
|
数据充足的生产环境 \\
|
||||||
|
\midrule
|
||||||
|
纯IK逆解(本文) &
|
||||||
|
无需训练数据;实时求解;体型适应性好 &
|
||||||
|
需合理设计任务约束与权重 &
|
||||||
|
实时重定向 \\
|
||||||
|
\bottomrule
|
||||||
|
\end{tabular}
|
||||||
|
\end{table}
|
||||||
|
|
||||||
|
\subsection{整体流程}
|
||||||
|
|
||||||
|
本系统的重定向流程如下:
|
||||||
|
|
||||||
|
\begin{center}
|
||||||
|
\begin{tcolorbox}[width=0.85\textwidth, colback=blue!5, colframe=blue!40,
|
||||||
|
boxrule=0.5pt, arc=3pt]
|
||||||
|
\centering
|
||||||
|
\textbf{输入} SMPL关节坐标序列 $[N, J, 3]$ \\[4pt]
|
||||||
|
$\downarrow$ \\[2pt]
|
||||||
|
坐标系变换(quat旋转,对齐机器人坐标系)\\[4pt]
|
||||||
|
$\downarrow$ \\[2pt]
|
||||||
|
根节点归一化 $\rightarrow$ 比例缩放 $\rightarrow$ 平移至waist高度 \\[4pt]
|
||||||
|
$\downarrow$ \\[2pt]
|
||||||
|
Yaw朝向对齐(固定根节点朝向)\\[4pt]
|
||||||
|
$\downarrow$ \\[2pt]
|
||||||
|
Savitzky-Golay 平滑滤波 \\[4pt]
|
||||||
|
$\downarrow$ \\[2pt]
|
||||||
|
设定IK追踪任务与权重 \\[4pt]
|
||||||
|
$\downarrow$ \\[2pt]
|
||||||
|
逐帧骨骼重定向(动态Anchor + 骨骼长度替换)\\[4pt]
|
||||||
|
$\downarrow$ \\[2pt]
|
||||||
|
QP差分IK求解 \\[4pt]
|
||||||
|
$\downarrow$ \\[2pt]
|
||||||
|
加权滑动窗口平滑 $\rightarrow$ 脚踝pitch几何覆写 \\[4pt]
|
||||||
|
$\downarrow$ \\[2pt]
|
||||||
|
三次样条插值升采样至90fps \\[4pt]
|
||||||
|
$\downarrow$ \\[2pt]
|
||||||
|
\textbf{输出} 关节角度序列(rad,$[N, 28]$)
|
||||||
|
\end{tcolorbox}
|
||||||
|
\end{center}
|
||||||
|
|
||||||
|
% 描述整体 pipeline,可以用 itemize 列出步骤
|
||||||
|
|
||||||
|
\subsection{坐标系处理}
|
||||||
|
|
||||||
|
\subsubsection{SMPL坐标系与机器人坐标系的对齐}
|
||||||
|
|
||||||
|
SMPL以骨盆(pelvis)为根节点,机器人以waist为躯干中心,两者物理意义最接近,因此将pelvis对齐到机器人waist位置。具体分两步:以pelvis为原点中心化后乘以缩放系数,再平移至机器人waist高度:
|
||||||
|
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
# 中心化 + 缩放
|
||||||
|
smpl_joints = (smpl_raw_seq - smpl_raw_seq[:, 0:1, :]) * self.SMPL_SCALE
|
||||||
|
# 平移至机器人waist高度
|
||||||
|
waist_pos = self.configuration.get_transform_frame_to_world("waist").translation
|
||||||
|
smpl_joints += waist_pos.reshape(1, 1, 3)
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
% 描述 quat = [0.5, 0.5, 0.5, 0.5] 的作用
|
||||||
|
|
||||||
|
\subsubsection{朝向对齐预处理}
|
||||||
|
|
||||||
|
大模型输出的动作可能包含根节点移动(如走圈),直接重定向会导致机器人跟随转向。因此对每帧计算髋部左右向量的水平偏转角,绕Z轴旋转补偿,使全程朝向与第0帧保持一致:
|
||||||
|
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
# 计算每帧髋部向量的yaw角
|
||||||
|
hip_vecs = smpl_joints[:, idx_r] - smpl_joints[:, idx_l]
|
||||||
|
hip_vecs[:, 2] = 0 # 投影到水平面
|
||||||
|
yaw_ref = np.arctan2(hip_vecs[0, 1], hip_vecs[0, 0])
|
||||||
|
yaw_all = np.arctan2(hip_vecs[:, 1], hip_vecs[:, 0])
|
||||||
|
|
||||||
|
# 绕Z轴旋转补偿,固定朝向
|
||||||
|
rot_mats = sRot.from_euler('z', yaw_ref - yaw_all).as_matrix()
|
||||||
|
centered = smpl_joints - smpl_joints[:, 0:1, :]
|
||||||
|
smpl_joints = np.einsum('nij,nkj->nki', rot_mats, centered) + smpl_joints[:, 0:1, :]
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
% 描述固定根节点朝向的处理逻辑
|
||||||
|
|
||||||
|
\subsection{骨骼重定向}
|
||||||
|
\begin{figure}[h]
|
||||||
|
\centering
|
||||||
|
\begin{minipage}{0.45\textwidth}
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=\textwidth]{before.png}
|
||||||
|
\caption{重定向前}
|
||||||
|
\end{minipage}
|
||||||
|
\hfill
|
||||||
|
\begin{minipage}{0.45\textwidth}
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=\textwidth]{after.png}
|
||||||
|
\caption{重定向后}
|
||||||
|
\end{minipage}
|
||||||
|
\caption{重定向前后对比:绿色为H1机器人关节点,蓝色为SMPL目标关节点}
|
||||||
|
\label{fig:retarget_compare}
|
||||||
|
\end{figure}
|
||||||
|
\subsubsection{动态Anchor设计}
|
||||||
|
|
||||||
|
SMPL人体与机器人结构不同,肩部和髋部的关节位置无法直接对应。若直接以SMPL的肩膀点作为anchor,会有两个问题:一是两者骨骼比例不同导致位置偏差;二是人体上肢挥动时SMPL肩膀点存在上下位移,而机器人肩部三个电机的结构无法复现这种位移。
|
||||||
|
|
||||||
|
因此每帧从机器人当前正运动学结果中读取肩部、髋部、颈部的真实世界坐标作为anchor,再以SMPL骨骼的方向信息驱动末端位置:
|
||||||
|
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
# 每帧从机器人正运动学读取anchor点
|
||||||
|
anchors = {
|
||||||
|
'l_shoulder': self.configuration.get_transform_frame_to_world(
|
||||||
|
"left_upper_arm").translation.copy(),
|
||||||
|
'r_shoulder': self.configuration.get_transform_frame_to_world(
|
||||||
|
"right_upper_arm").translation.copy(),
|
||||||
|
'l_thigh': self.configuration.get_transform_frame_to_world(
|
||||||
|
"left_thigh").translation.copy(),
|
||||||
|
'r_thigh': self.configuration.get_transform_frame_to_world(
|
||||||
|
"right_thigh").translation.copy(),
|
||||||
|
'neck': self.configuration.get_transform_frame_to_world(
|
||||||
|
"neck_linkage").translation.copy(),
|
||||||
|
}
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
同时,利用SMPL的spine1、left\_collar、right\_collar三点构造正交基,得到躯干朝向,用于约束机器人胸部旋转,间接驱动上肢姿态跟随躯干运动:
|
||||||
|
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
# 三点构造胸部正交基
|
||||||
|
up = _normalize((p_l_collar + p_r_collar) / 2.0 - p_spine3)
|
||||||
|
right = _normalize(p_l_collar - p_r_collar)
|
||||||
|
forward = _normalize(np.cross(right, up))
|
||||||
|
right = _normalize(np.cross(up, forward))
|
||||||
|
chest_rot = np.column_stack([forward, right, up])
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
% 描述为什么要用动态anchor,以及如何实现
|
||||||
|
|
||||||
|
\subsubsection{链式骨骼长度替换}
|
||||||
|
|
||||||
|
SMPL与机器人的骨骼长度不同,直接使用SMPL关节坐标会导致末端位置偏差。解决方案是保留SMPL各骨骼段的方向向量,将长度替换为机器人实际物理尺寸,从anchor点出发链式计算各关节位置,使末端(手、脚)能够正确对齐:
|
||||||
|
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
# 机器人实际骨骼长度(米)
|
||||||
|
ROBOT_DIMS = {
|
||||||
|
'thigh': 0.0832, # 髋 -> 膝
|
||||||
|
'calf': 0.1105, # 膝 -> 踝
|
||||||
|
'upper_arm': 0.07579, # 肩 -> 肘
|
||||||
|
'forearm': 0.04739, # 肘 -> 腕
|
||||||
|
'neck2head': 0.022487329, # 颈部 -> 头
|
||||||
|
}
|
||||||
|
|
||||||
|
# 以anchor为父节点,沿SMPL方向链式扩展(以左腿为例)
|
||||||
|
nj[:, b['left_hip']] = anchors['l_thigh']
|
||||||
|
nj[:, b['left_knee']] = anchors['l_thigh'] \
|
||||||
|
+ _normalize(j[:, b['left_knee']] - j[:, b['left_hip']]) * d['thigh']
|
||||||
|
nj[:, b['left_ankle']] = nj[:, b['left_knee']] \
|
||||||
|
+ _normalize(j[:, b['left_ankle']] - j[:, b['left_knee']]) * d['calf']
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
左右臂同理,从肩部anchor出发,依次计算肘、腕位置。经过链式替换后,末端关节坐标既保留了SMPL动作的姿态方向,又符合机器人的实际骨骼比例。
|
||||||
|
|
||||||
|
% 描述 apply_bone_retargeting_single 的逻辑
|
||||||
|
|
||||||
|
\subsection{差分IK求解}
|
||||||
|
|
||||||
|
\subsubsection{PINK框架介绍}
|
||||||
|
|
||||||
|
PINK(Python Inverse kiNematics)是基于Pinocchio的差分IK框架。Pinocchio负责机器人运动学/动力学计算,PINK在其基础上将IK问题构造为二次规划(QP)问题,通过定义多个带权重的\textbf{任务}(Task)和\textbf{约束}(Limit)来描述求解目标。
|
||||||
|
|
||||||
|
每个任务对应一个末端执行器的位置或旋转目标,权重决定各任务的优先级。求解器在满足关节限位约束的前提下,每帧求解一个关节速度增量,再积分更新机器人配置,从而逐帧追踪目标轨迹。本系统使用quadprog作为底层QP求解器,阻尼系数设为$10^{-3}$防止奇异。
|
||||||
|
|
||||||
|
% 简要介绍 PINK 和 Pinocchio
|
||||||
|
|
||||||
|
\subsubsection{任务设计与权重}
|
||||||
|
|
||||||
|
系统共定义以下IK任务,各任务的位置权重与旋转权重如表所示:
|
||||||
|
|
||||||
|
\begin{table}[h]
|
||||||
|
\centering
|
||||||
|
\caption{IK任务权重配置}
|
||||||
|
\begin{tabular}{llcc}
|
||||||
|
\toprule
|
||||||
|
\textbf{机器人Link} & \textbf{对应SMPL关节} & \textbf{位置权重} & \textbf{旋转权重} \\
|
||||||
|
\midrule
|
||||||
|
chest & — & 0.0 & 50.0 \\
|
||||||
|
left\_hand / right\_hand & left\_wrist / right\_wrist & 10.0 & 0.0 \\
|
||||||
|
left\_foot / right\_foot & left\_ankle / right\_ankle & 10.0 & 1.0 \\
|
||||||
|
left\_force\_arm / right\_force\_arm & left\_elbow / right\_elbow & 5.0 & 0.0 \\
|
||||||
|
left\_calf / right\_calf & left\_knee / right\_knee & 5.0 & 0.0 \\
|
||||||
|
head & head & 1.0 & 5.0 \\
|
||||||
|
\bottomrule
|
||||||
|
\end{tabular}
|
||||||
|
\end{table}
|
||||||
|
|
||||||
|
chest任务不追位置,只追旋转,用于约束躯干朝向防止后仰;手和脚作为末端执行器位置权重最高;肘和膝作为中间关节权重较低,主要用于引导肢体方向;头部以旋转约束为主。此外还加入了一个低权重(0.1)的PostureTask作为软约束,防止未被追踪的关节乱飘:
|
||||||
|
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
self.posture_task = pink.tasks.PostureTask(self.model)
|
||||||
|
self.posture_task.set_target(self.q_ref)
|
||||||
|
self.posture_task.cost = 0.1
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
% 描述各个 FrameTask 的权重设计思路
|
||||||
|
|
||||||
|
\subsubsection{躯干朝向约束}
|
||||||
|
|
||||||
|
IK求解时若不对躯干朝向加以约束,机器人上半身容易出现后仰或侧倾。为此单独设置一个chest的FrameTask,只追旋转不追位置(位置权重为0,旋转权重为50),每帧从SMPL的spine1、left\_collar、right\_collar三点构造正交基作为目标旋转矩阵(见2.4.1节),强制机器人胸部朝向与SMPL躯干保持一致。
|
||||||
|
|
||||||
|
由于位置不强制追踪,chest的世界坐标始终取机器人当前真实位置,避免与其他任务产生冲突:
|
||||||
|
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
chest_pos = self.configuration.get_transform_frame_to_world("chest").translation.copy()
|
||||||
|
self.chest_task.set_target(pin.SE3(chest_rot, chest_pos))
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
% 描述用 spine3/left_collar/right_collar 三点确定胸部朝向的方法
|
||||||
|
|
||||||
|
\subsubsection{头部朝向处理}
|
||||||
|
|
||||||
|
头部朝向通过两种方式处理。若上游提供了\lstinline{head_rot_mats}(局部旋转矩阵),则将其与当前帧的躯干旋转矩阵相乘得到头部世界朝向;若未提供则只追位置,旋转使用单位矩阵:
|
||||||
|
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
if smpl_name == "head" and head_rot_mats is not None:
|
||||||
|
# 世界朝向 = 躯干朝向 x 头部局部旋转
|
||||||
|
task.set_target(pin.SE3(chest_rot @ head_rot_mats[i], limited_targets[smpl_name]))
|
||||||
|
else:
|
||||||
|
task.set_target(pin.SE3(np.eye(3), limited_targets[smpl_name]))
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
由于\lstinline{head_rot_mats}是相对于父关节的局部旋转,对于包含大幅根节点移动的动作(如走圈),预处理阶段会自动检测并清除旋转向量的Yaw分量,避免头部跟随身体转向产生突变。
|
||||||
|
|
||||||
|
% 描述头部朝向的处理方法
|
||||||
|
|
||||||
|
\subsection{数据处理与平滑}
|
||||||
|
|
||||||
|
\subsubsection{插值扩帧}
|
||||||
|
|
||||||
|
IK求解在20fps上运行,完成后对关节角度序列做三次样条插值升采样至90fps。在关节空间插值比在笛卡尔空间插值更物理合理,且计算开销小:
|
||||||
|
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
interp = interp1d(t_orig, sim_dof, axis=0, kind='cubic')
|
||||||
|
sim_dof = interp(t_new)
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
% 描述从20fps插值到90fps的方法
|
||||||
|
|
||||||
|
\subsubsection{加权滑动滤波}
|
||||||
|
|
||||||
|
对IK输出的关节角度序列做线性加权滑动均值滤波(窗口7帧),越近的帧权重越高,有效抑制IK求解引入的高频抖动。该滤波方法在机器人动作重定向领域被广泛采用:
|
||||||
|
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
w = np.arange(1, window_size + 1, dtype=float)
|
||||||
|
w /= w.sum() # 线性权重归一化,越新的帧权重越大
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
% 描述 WeightedMovingFilter
|
||||||
|
|
||||||
|
\subsubsection{关节限位约束}
|
||||||
|
|
||||||
|
在IK求解时加入ConfigurationLimit约束,将28个关节的角度限制在物理允许范围内,防止求解结果超出机器人实际关节行程:
|
||||||
|
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
# 将限位写入Pinocchio模型
|
||||||
|
self.model.lowerPositionLimit[q_idx] = H1Config.JOINT_LIMITS[idx, 0]
|
||||||
|
self.model.upperPositionLimit[q_idx] = H1Config.JOINT_LIMITS[idx, 1]
|
||||||
|
self.config_limit = ConfigurationLimit(self.model)
|
||||||
|
|
||||||
|
# IK求解时传入约束
|
||||||
|
velocity = pink.solve_ik(
|
||||||
|
self.configuration, self.tasks, dt,
|
||||||
|
solver="quadprog", damping=1e-3,
|
||||||
|
limits=[self.config_limit],
|
||||||
|
)
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
% 描述 ConfigurationLimit 的使用
|
||||||
|
|
||||||
|
\subsubsection{脚踝角度计算}
|
||||||
|
|
||||||
|
机器人没有脚掌关节,脚踝pitch角度无法通过IK直接求解。因此从SMPL几何信息中提取每帧小腿方向向量与脚掌方向向量的夹角,以第0帧(站立姿态)为基准计算相对变化量,直接覆写到脚踝pitch电机:
|
||||||
|
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
# 计算小腿与脚掌方向向量的夹角
|
||||||
|
shin = _normalize(ankle - knee)
|
||||||
|
toes = _normalize(foot - ankle)
|
||||||
|
angle = np.arccos(np.clip((shin * toes).sum(axis=-1), -1.0, 1.0))
|
||||||
|
|
||||||
|
# 以第0帧为中性角基准,限制在关节限位内
|
||||||
|
pitch = angle - angle[0]
|
||||||
|
pitch = np.clip(pitch, lo, hi)
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
% 描述从小腿/脚掌方向向量计算脚踝pitch角的方法
|
||||||
|
|
||||||
|
\subsection{其他}
|
||||||
|
|
||||||
|
\subsubsection{遥操作与实时重定向的区别}
|
||||||
|
|
||||||
|
目前业内已有端到端的实时遥操作方案(如GR-1、AnyTeleop等),直接从摄像头到机器人控制信号,延迟极低。本系统与其定位不同,对比如下:
|
||||||
|
|
||||||
|
\begin{table}[h]
|
||||||
|
\centering
|
||||||
|
\caption{实时遥操作方案与本系统对比}
|
||||||
|
\begin{tabular}{p{3cm}p{5.5cm}p{5.5cm}}
|
||||||
|
\toprule
|
||||||
|
& \textbf{实时遥操作(如GMR)} & \textbf{本系统(GVHMR + IK)} \\
|
||||||
|
\midrule
|
||||||
|
\textbf{输入来源} & 实时摄像头 & 视频文件或大模型npy输出 \\
|
||||||
|
\textbf{实时性} & 极低延迟,在线处理 & 离线为主,单帧$\approx$0.4ms \\
|
||||||
|
\textbf{精度} & 人体捕捉精度较低,但足够还原动作 & GVHMR精度较高 \\
|
||||||
|
\textbf{机器人泛化性} & 换机器人需重新训练模型 & 只需修改URDF和骨骼参数,无需重训 \\
|
||||||
|
\textbf{适用场景} & 实时控制、遥操作 & 动作生成、离线批量处理 \\
|
||||||
|
\textbf{主要优势} & 延迟低、部署简单 & 通用性强,兼容多种输入源 \\
|
||||||
|
\bottomrule
|
||||||
|
\end{tabular}
|
||||||
|
\end{table}
|
||||||
|
|
||||||
|
本系统优先接入大模型生成的npy动作数据,以通用IK重定向为核心,机器人结构发生变化时只需更新URDF和骨骼长度参数即可适配,无需重新训练任何模型,维护成本低。
|
||||||
|
|
||||||
|
\subsubsection{局部四肢避障方法}
|
||||||
|
|
||||||
|
|
||||||
|
在动作模仿过程中,若摄像头检测到障碍物与机器人四肢存在碰撞风险,需要对目标关节点位进行实时修正。
|
||||||
|
|
||||||
|
\textbf{基本思路}:不修改IK框架,而是在骨骼重定向阶段对SMPL关节点位进行几何修正,将避障后的新点位作为IK追踪目标传入。
|
||||||
|
|
||||||
|
\textbf{几何避障原理}:以手臂为例,肩膀、肘部、手腕三点构成一个两边长度固定(大臂长、小臂长)的运动链。当大臂或小臂检测到与障碍物碰撞时,在保持骨骼长度不变的约束下,迭代计算绕障后的新关节位置,使整个手臂绕过障碍物的同时保持人体物理结构不变形。腿部同理,由髋、膝、踝三点构成固定长度运动链做同样处理。
|
||||||
|
|
||||||
|
\textbf{局限性}:该方法基于纯几何计算,时效性好,适用于简单的局部避障场景。对于需要腰部扭转、重心转移等全身协调配合的复杂避障情况,单纯修正四肢点位无法保证整体姿态合理性,需要引入更完整的全身运动规划方案。
|
||||||
|
|
||||||
|
\begin{figure}[h]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=\textwidth]{arm_avoidance.png}
|
||||||
|
\caption{局部四肢避障几何方法示意图}
|
||||||
|
\label{fig:arm_avoidance}
|
||||||
|
\end{figure}
|
||||||
|
% 在这里写你对整个重定向方法的理解,遇到的问题和解决思路
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
|
||||||
|
% ============================================================
|
||||||
|
% 第三章:问答记录
|
||||||
|
% ============================================================
|
||||||
|
\section{常见踩坑}
|
||||||
|
|
||||||
|
\begin{qabox}{quat旋转的作用是什么?}
|
||||||
|
\end{qabox}
|
||||||
|
|
||||||
|
\begin{answerbox}
|
||||||
|
大模型输出的SMPL关节坐标以Y轴朝上为标准坐标系,而本系统机器人重定向以Z轴朝上为基准。若不做坐标系变换,输入的SMPL人体在机器人坐标系下呈躺倒状态,无法正常重定向。
|
||||||
|
|
||||||
|
通过四元数 $q=[0.5, 0.5, 0.5, 0.5]$ 对应的旋转矩阵,将Y轴朝上变换为Z轴朝上:
|
||||||
|
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
rot = sRot.from_quat([0.5, 0.5, 0.5, 0.5]).as_matrix()
|
||||||
|
smpl_raw_seq = target_motion @ rot.T # [T, J, 3]
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
对于GVHMR视频提取的SMPL数据,输出已是Z轴朝上,无需做Y轴到Z轴的变换,只需绕Z轴旋转$-90°$调整朝向,对应quat参数为$[0, 0, -0.707, 0.707]$ (参考服务器端GVHMR目录下的逆解文件)。
|
||||||
|
\end{answerbox}
|
||||||
|
\vspace{1em}
|
||||||
|
|
||||||
|
% ---- 继续添加 Q&A ----
|
||||||
|
|
||||||
|
\subsection{骨骼重定向相关}
|
||||||
|
|
||||||
|
\begin{qabox}{若不将躯干与两臂任务解耦会有什么后果?}
|
||||||
|
\end{qabox}
|
||||||
|
|
||||||
|
\begin{answerbox}
|
||||||
|
若直接以SMPL肩膀点作为两臂IK追踪的anchor,由于机器人与SMPL骨骼比例不同,肩膀点无法完全对齐,导致以肩膀为起点的手肘、手腕等末端追踪点整体偏移,IK始终存在残差。
|
||||||
|
|
||||||
|
更严重的问题是,PINK本质上求解的是QP问题,当多个任务存在冲突时,求解器会在各任务间做权重妥协。若躯干与手臂任务耦合,某一侧手臂恰好能追上目标而另一侧追不上时,QP求解器为了整体最优会将误差集中到某个关节,导致该关节的轴向电机出现突变甚至疯转。
|
||||||
|
|
||||||
|
通过动态Anchor设计,每帧以机器人自身正运动学的肩膀位置为起点,将躯干运动与手臂末端追踪解耦,从根本上避免了上述问题。
|
||||||
|
\end{answerbox}
|
||||||
|
% Q&A
|
||||||
|
|
||||||
|
\subsection{IK求解相关}
|
||||||
|
|
||||||
|
\begin{qabox}{为什么不先插值到90fps再进行IK求解?}
|
||||||
|
\end{qabox}
|
||||||
|
|
||||||
|
\begin{answerbox}
|
||||||
|
IK求解的耗时与帧数成正比,若先插值到90fps再求解,计算量是当前方案的4.5倍。而先在20fps上完成IK求解,再对关节角度序列做三次样条插值升采样至90fps,精度损失极小,因为相邻帧间的关节角度变化平滑,插值能够很好地还原中间帧。
|
||||||
|
|
||||||
|
因此选择先IK后插值的方案,在几乎不影响动作质量的前提下将IK阶段耗时降低至原来的$\frac{1}{4.5}$,是性价比最高的做法。
|
||||||
|
\end{answerbox}
|
||||||
|
|
||||||
|
\begin{qabox}{为什么不在IK求解过程中加入速度控制?}
|
||||||
|
\end{qabox}
|
||||||
|
|
||||||
|
\begin{answerbox}
|
||||||
|
主要有三个原因:
|
||||||
|
|
||||||
|
第一,职责解耦。重定向模块只负责将人体动作映射为机器人关节角度,速度控制属于运动控制层的职责,两者混合会导致模块边界模糊,出现问题时难以定位。
|
||||||
|
|
||||||
|
第二,仿真与现实存在差距。PINK求解的是仿真环境下的机器人状态,加入速度控制后轨迹会产生延迟跟踪效果,而这个延迟在真实机器人上的表现与仿真并不一致,反而引入额外误差。
|
||||||
|
|
||||||
|
第三,需求已满足。本系统的目标是离线生成某段动作对应的机器人关节角度序列,并不需要在线实时跟踪,因此静态的角度序列输出已经完全满足需求,无需引入速度控制增加复杂度。
|
||||||
|
\end{answerbox}
|
||||||
|
|
||||||
|
|
||||||
|
% Q&A
|
||||||
|
|
||||||
|
% ============================================================
|
||||||
|
% 附录
|
||||||
|
% ============================================================
|
||||||
|
\newpage
|
||||||
|
\section{后续规划}
|
||||||
|
\subsection{目标}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{训练机器人行走:} 利用重定向模块生成的高质量行走动作序列作为参考轨迹,通过强化学习训练机器人在仿真环境中实现稳定行走。
|
||||||
|
|
||||||
|
\item \textbf{去掉固定根节点限制:} 当前重定向模块输出的电机角度序列以固定waist为前提,无法直接在真实环境中执行带位移的动作。目标是结合强化学习,训练机器人在真实动力学约束下完成动作模仿,使其能够在现实环境中真正执行出对应动作。
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\subsection{计划路线}
|
||||||
|
当前调研的技术路线如下:
|
||||||
|
|
||||||
|
\begin{center}
|
||||||
|
\begin{tcolorbox}[width=0.85\textwidth, colback=blue!5, colframe=blue!40,
|
||||||
|
boxrule=0.5pt, arc=3pt]
|
||||||
|
\centering
|
||||||
|
\textbf{输入} 大模型生成 / 视频提取 \\[4pt]
|
||||||
|
$\downarrow$ \\[2pt]
|
||||||
|
转换为SMPL关节坐标序列(.npy) \\[4pt]
|
||||||
|
$\downarrow$ \\[2pt]
|
||||||
|
动作重定向模块 $\rightarrow$ 输出电机角度序列(dof) \\[4pt]
|
||||||
|
$\downarrow$ \\[2pt]
|
||||||
|
接入强化学习模块 \\[2pt]
|
||||||
|
(结合动力学信息对角度序列进行调整与优化) \\[4pt]
|
||||||
|
$\downarrow$ \\[2pt]
|
||||||
|
\textbf{输出} 可在真实环境执行的机器人动作
|
||||||
|
\end{tcolorbox}
|
||||||
|
\end{center}
|
||||||
|
|
||||||
|
\subsection{参考方法}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{humanoid-gym}:基于PPO的H1行走训练,用于验证仿真环境与机器人配置。
|
||||||
|
\item \textbf{ExBody2}:基于AMP框架的动作模仿,以重定向模块输出的dof序列作为参考轨迹,对重定向误差容忍度较高。
|
||||||
|
\item \textbf{OmniH2O}:全身精确动作模仿备选方案,关节角度直接跟踪,还原度更高但对重定向精度要求更高。
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
\appendix
|
||||||
|
|
||||||
|
\section{关键参数说明}
|
||||||
|
|
||||||
|
\begin{table}[h]
|
||||||
|
\centering
|
||||||
|
\caption{重定向关键参数}
|
||||||
|
\begin{tabular}{lll}
|
||||||
|
\toprule
|
||||||
|
\textbf{参数名} & \textbf{值} & \textbf{说明} \\
|
||||||
|
\midrule
|
||||||
|
\texttt{scale} & 0.2466 & SMPL到机器人的缩放比例 \\
|
||||||
|
\texttt{aim\_fps} & 90 & 目标帧率 \\
|
||||||
|
\texttt{substeps} & 2 & IK每帧子步数 \\
|
||||||
|
\texttt{max\_step} & 0.01 & 目标点每步最大移动距离(m) \\
|
||||||
|
\texttt{damping} & 1e-3 & IK阻尼系数 \\
|
||||||
|
\bottomrule
|
||||||
|
\end{tabular}
|
||||||
|
\end{table}
|
||||||
|
|
||||||
|
\end{document}
|
||||||
Binary file not shown.
+363
@@ -0,0 +1,363 @@
|
|||||||
|
\documentclass[12pt, a4paper]{article}
|
||||||
|
|
||||||
|
% ========== 基础包 ==========
|
||||||
|
\usepackage[UTF8]{ctex} % 中文支持
|
||||||
|
\usepackage[margin=2.5cm]{geometry} % 页边距
|
||||||
|
\usepackage{titlesec} % 章节标题格式
|
||||||
|
\usepackage{titletoc} % 目录格式
|
||||||
|
\usepackage{fancyhdr} % 页眉页脚
|
||||||
|
\usepackage{listings} % 代码块
|
||||||
|
\usepackage{xcolor} % 颜色
|
||||||
|
\usepackage{graphicx} % 图片
|
||||||
|
\usepackage{amsmath} % 数学公式
|
||||||
|
\usepackage{amssymb} % 数学符号
|
||||||
|
\usepackage{booktabs} % 表格
|
||||||
|
\usepackage{enumitem} % 列表格式
|
||||||
|
\usepackage{tcolorbox} % 彩色盒子
|
||||||
|
\usepackage{fontawesome5} % 图标
|
||||||
|
\usepackage{setspace} % 行距
|
||||||
|
\usepackage{hyperref} % 超链接
|
||||||
|
|
||||||
|
% ========== 页面设置 ==========
|
||||||
|
\onehalfspacing
|
||||||
|
|
||||||
|
% ========== 可修改的文档信息 ==========
|
||||||
|
\newcommand{\doctitle}{XXXX技术文档}
|
||||||
|
\newcommand{\docsubtitle}{XXXX系统设计与实现}
|
||||||
|
\newcommand{\projectname}{XXXX项目}
|
||||||
|
\newcommand{\docauthor}{XXXX}
|
||||||
|
\newcommand{\docversion}{v1.0}
|
||||||
|
\newcommand{\docdescription}{本文档用于说明XXXX项目的设计、实现、测试及维护方法。}
|
||||||
|
|
||||||
|
% ========== 页眉页脚 ==========
|
||||||
|
\pagestyle{fancy}
|
||||||
|
\fancyhf{}
|
||||||
|
\fancyhead[L]{\small \doctitle}
|
||||||
|
\fancyhead[R]{\small \leftmark}
|
||||||
|
\fancyfoot[C]{\thepage}
|
||||||
|
\renewcommand{\headrulewidth}{0.4pt}
|
||||||
|
|
||||||
|
% ========== 颜色设置 ==========
|
||||||
|
\definecolor{codebg}{RGB}{245, 245, 245}
|
||||||
|
\definecolor{codeframe}{RGB}{200, 200, 200}
|
||||||
|
\definecolor{codegreen}{rgb}{0,0.6,0}
|
||||||
|
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
|
||||||
|
\definecolor{codepurple}{rgb}{0.58,0,0.82}
|
||||||
|
|
||||||
|
% ========== 超链接设置 ==========
|
||||||
|
\hypersetup{
|
||||||
|
colorlinks=true,
|
||||||
|
linkcolor=blue!70!black,
|
||||||
|
urlcolor=blue!70!black,
|
||||||
|
citecolor=green!60!black,
|
||||||
|
bookmarks=true,
|
||||||
|
bookmarksnumbered=true,
|
||||||
|
pdftitle={\doctitle},
|
||||||
|
pdfauthor={\docauthor}
|
||||||
|
}
|
||||||
|
|
||||||
|
% ========== 代码块设置 ==========
|
||||||
|
\lstdefinestyle{pythonstyle}{
|
||||||
|
backgroundcolor=\color{codebg},
|
||||||
|
commentstyle=\color{codegreen},
|
||||||
|
keywordstyle=\color{blue}\bfseries,
|
||||||
|
numberstyle=\tiny\color{codegray},
|
||||||
|
stringstyle=\color{codepurple},
|
||||||
|
basicstyle=\ttfamily\footnotesize,
|
||||||
|
breakatwhitespace=false,
|
||||||
|
breaklines=true,
|
||||||
|
captionpos=b,
|
||||||
|
keepspaces=true,
|
||||||
|
numbers=left,
|
||||||
|
numbersep=5pt,
|
||||||
|
showspaces=false,
|
||||||
|
showstringspaces=false,
|
||||||
|
showtabs=false,
|
||||||
|
tabsize=4,
|
||||||
|
frame=single,
|
||||||
|
rulecolor=\color{codeframe},
|
||||||
|
language=Python
|
||||||
|
}
|
||||||
|
|
||||||
|
\lstdefinestyle{bashstyle}{
|
||||||
|
backgroundcolor=\color{codebg},
|
||||||
|
basicstyle=\ttfamily\footnotesize,
|
||||||
|
breaklines=true,
|
||||||
|
frame=single,
|
||||||
|
rulecolor=\color{codeframe},
|
||||||
|
language=bash,
|
||||||
|
commentstyle=\color{codegreen},
|
||||||
|
keywordstyle=\color{blue}
|
||||||
|
}
|
||||||
|
|
||||||
|
\lstset{style=pythonstyle}
|
||||||
|
|
||||||
|
% ========== 彩色盒子样式 ==========
|
||||||
|
\tcbuselibrary{skins, breakable}
|
||||||
|
|
||||||
|
\newtcolorbox{qabox}[2][]{
|
||||||
|
enhanced,
|
||||||
|
breakable,
|
||||||
|
colback=blue!5!white,
|
||||||
|
colframe=blue!60!black,
|
||||||
|
fonttitle=\bfseries,
|
||||||
|
title={Q: #2},
|
||||||
|
#1
|
||||||
|
}
|
||||||
|
|
||||||
|
\newtcolorbox{answerbox}[1][]{
|
||||||
|
enhanced,
|
||||||
|
breakable,
|
||||||
|
colback=green!5!white,
|
||||||
|
colframe=green!60!black,
|
||||||
|
leftrule=4pt,
|
||||||
|
#1
|
||||||
|
}
|
||||||
|
|
||||||
|
\newtcolorbox{filebox}[2][]{
|
||||||
|
enhanced,
|
||||||
|
breakable,
|
||||||
|
colback=gray!10!white,
|
||||||
|
colframe=gray!60!black,
|
||||||
|
fonttitle=\bfseries\ttfamily,
|
||||||
|
title={\faFile\ #2},
|
||||||
|
#1
|
||||||
|
}
|
||||||
|
|
||||||
|
% ========== 章节标题格式 ==========
|
||||||
|
\titleformat{\section}
|
||||||
|
{\Large\bfseries\color{blue!70!black}}
|
||||||
|
{\thesection}{1em}{}
|
||||||
|
[\titlerule]
|
||||||
|
|
||||||
|
\titleformat{\subsection}
|
||||||
|
{\large\bfseries\color{blue!50!black}}
|
||||||
|
{\thesubsection}{1em}{}
|
||||||
|
|
||||||
|
\titleformat{\subsubsection}
|
||||||
|
{\normalsize\bfseries}
|
||||||
|
{\thesubsubsection}{1em}{}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
|
||||||
|
% ========== 封面 ==========
|
||||||
|
\begin{titlepage}
|
||||||
|
\centering
|
||||||
|
\vspace*{3cm}
|
||||||
|
|
||||||
|
{\Huge\bfseries \doctitle\\[0.5em]
|
||||||
|
\Large \docsubtitle}
|
||||||
|
|
||||||
|
\vspace{2cm}
|
||||||
|
\rule{\linewidth}{0.5mm}
|
||||||
|
\vspace{1cm}
|
||||||
|
|
||||||
|
{\large
|
||||||
|
\begin{tabular}{ll}
|
||||||
|
\textbf{项目名称:} & \projectname \\[0.5em]
|
||||||
|
\textbf{作者:} & \docauthor \\[0.5em]
|
||||||
|
\textbf{日期:} & \today \\[0.5em]
|
||||||
|
\textbf{版本:} & \docversion \\
|
||||||
|
\end{tabular}
|
||||||
|
}
|
||||||
|
|
||||||
|
\vspace{1cm}
|
||||||
|
\rule{\linewidth}{0.5mm}
|
||||||
|
|
||||||
|
\vfill
|
||||||
|
{\small \docdescription}
|
||||||
|
\end{titlepage}
|
||||||
|
|
||||||
|
% ========== 目录 ==========
|
||||||
|
\tableofcontents
|
||||||
|
\newpage
|
||||||
|
|
||||||
|
% ============================================================
|
||||||
|
% 使用时可直接修改下面各章节,也可以复制或删除任意示例
|
||||||
|
% ============================================================
|
||||||
|
\section{文档概述}
|
||||||
|
|
||||||
|
\subsection{编写目的}
|
||||||
|
XXXX:说明本文档解决什么问题、面向哪些读者,以及预期达到的目标。
|
||||||
|
|
||||||
|
\subsection{项目背景}
|
||||||
|
XXXX:简要介绍项目来源、应用场景和当前状态。
|
||||||
|
|
||||||
|
\subsection{术语说明}
|
||||||
|
\begin{table}[htbp]
|
||||||
|
\centering
|
||||||
|
\caption{术语说明示例}
|
||||||
|
\begin{tabular}{ll}
|
||||||
|
\toprule
|
||||||
|
\textbf{术语} & \textbf{说明} \\
|
||||||
|
\midrule
|
||||||
|
XXXX & 填写术语的完整名称及含义 \\
|
||||||
|
XXXX & 填写缩写、单位或专有概念 \\
|
||||||
|
\bottomrule
|
||||||
|
\end{tabular}
|
||||||
|
\end{table}
|
||||||
|
|
||||||
|
\section{系统设计}
|
||||||
|
|
||||||
|
\subsection{总体架构}
|
||||||
|
XXXX:描述系统组成、模块关系、数据流和部署方式。
|
||||||
|
|
||||||
|
\subsection{处理流程}
|
||||||
|
\begin{enumerate}
|
||||||
|
\item XXXX:填写流程的第一步。
|
||||||
|
\item XXXX:填写流程的第二步。
|
||||||
|
\item XXXX:填写流程的第三步。
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
\subsection{接口说明}
|
||||||
|
\begin{table}[htbp]
|
||||||
|
\centering
|
||||||
|
\caption{接口说明示例}
|
||||||
|
\begin{tabular}{llll}
|
||||||
|
\toprule
|
||||||
|
\textbf{接口} & \textbf{输入} & \textbf{输出} & \textbf{说明} \\
|
||||||
|
\midrule
|
||||||
|
XXXX & XXXX & XXXX & 填写接口用途 \\
|
||||||
|
\bottomrule
|
||||||
|
\end{tabular}
|
||||||
|
\end{table}
|
||||||
|
|
||||||
|
\section{程序文件说明}
|
||||||
|
|
||||||
|
\subsection{核心文件}
|
||||||
|
\begin{filebox}{\texttt{xxxx.py}}
|
||||||
|
\textbf{功能:} XXXX:填写文件的主要作用。\\[0.5em]
|
||||||
|
|
||||||
|
\textbf{主要类/函数:}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{XXXX} —— 填写类或函数的作用
|
||||||
|
\item \texttt{xxxx()} —— 填写输入、输出及处理逻辑
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\textbf{输入:} XXXX:填写数据类型、单位和维度。\\
|
||||||
|
|
||||||
|
\textbf{输出:} XXXX:填写返回值、保存文件或执行结果。\\
|
||||||
|
|
||||||
|
\textbf{依赖:} XXXX:填写库、环境或外部服务。
|
||||||
|
\end{filebox}
|
||||||
|
|
||||||
|
\subsection{目录结构}
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
project/
|
||||||
|
|-- src/ # XXXX:源代码
|
||||||
|
|-- config/ # XXXX:配置文件
|
||||||
|
|-- tests/ # XXXX:测试代码
|
||||||
|
`-- README.md # XXXX:使用说明
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
\section{关键方法与原理}
|
||||||
|
|
||||||
|
\subsection{方法概述}
|
||||||
|
XXXX:介绍核心方法的基本思想、适用条件和主要优势。
|
||||||
|
|
||||||
|
\subsection{数学模型}
|
||||||
|
XXXX:在正文中解释公式中各符号的物理意义。例如:
|
||||||
|
\begin{equation}
|
||||||
|
y = f(x;\theta)
|
||||||
|
\label{eq:example}
|
||||||
|
\end{equation}
|
||||||
|
其中,$x$ 表示XXXX,$y$ 表示XXXX,$\theta$ 表示XXXX。
|
||||||
|
|
||||||
|
\subsection{算法步骤}
|
||||||
|
\begin{enumerate}
|
||||||
|
\item XXXX:准备输入数据。
|
||||||
|
\item XXXX:执行核心计算。
|
||||||
|
\item XXXX:输出并检查结果。
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
\section{实现说明}
|
||||||
|
|
||||||
|
\subsection{环境配置}
|
||||||
|
\begin{lstlisting}[style=bashstyle]
|
||||||
|
# XXXX:填写环境创建或依赖安装命令
|
||||||
|
python --version
|
||||||
|
pip install xxxx
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
\subsection{核心代码}
|
||||||
|
\begin{lstlisting}[caption={XXXX代码示例}]
|
||||||
|
def main(input_data):
|
||||||
|
"""XXXX:填写函数说明。"""
|
||||||
|
result = input_data
|
||||||
|
return result
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
\subsection{配置参数}
|
||||||
|
\begin{table}[htbp]
|
||||||
|
\centering
|
||||||
|
\caption{关键参数说明}
|
||||||
|
\begin{tabular}{llll}
|
||||||
|
\toprule
|
||||||
|
\textbf{参数} & \textbf{默认值} & \textbf{单位} & \textbf{说明} \\
|
||||||
|
\midrule
|
||||||
|
\texttt{xxxx} & XXXX & XXXX & 填写参数作用 \\
|
||||||
|
\texttt{xxxx} & XXXX & XXXX & 填写取值范围 \\
|
||||||
|
\bottomrule
|
||||||
|
\end{tabular}
|
||||||
|
\end{table}
|
||||||
|
|
||||||
|
\section{测试与结果}
|
||||||
|
|
||||||
|
\subsection{测试环境}
|
||||||
|
XXXX:填写硬件、操作系统、软件版本和测试数据。
|
||||||
|
|
||||||
|
\subsection{测试方法}
|
||||||
|
XXXX:填写测试步骤、对照条件和评价指标。
|
||||||
|
|
||||||
|
\subsection{结果分析}
|
||||||
|
\begin{table}[htbp]
|
||||||
|
\centering
|
||||||
|
\caption{测试结果示例}
|
||||||
|
\begin{tabular}{lll}
|
||||||
|
\toprule
|
||||||
|
\textbf{测试项} & \textbf{结果} & \textbf{结论} \\
|
||||||
|
\midrule
|
||||||
|
XXXX & XXXX & 通过/不通过 \\
|
||||||
|
\bottomrule
|
||||||
|
\end{tabular}
|
||||||
|
\end{table}
|
||||||
|
|
||||||
|
% 插入图片时取消下面代码的注释,并上传对应图片文件
|
||||||
|
% \begin{figure}[htbp]
|
||||||
|
% \centering
|
||||||
|
% \includegraphics[width=0.8\linewidth]{images/xxxx.png}
|
||||||
|
% \caption{XXXX:填写图片说明}
|
||||||
|
% \label{fig:example}
|
||||||
|
% \end{figure}
|
||||||
|
|
||||||
|
\section{常见问题}
|
||||||
|
|
||||||
|
\begin{qabox}{XXXX:填写常见问题?}
|
||||||
|
\begin{answerbox}
|
||||||
|
XXXX:说明问题现象、产生原因、排查步骤和解决方法。
|
||||||
|
\end{answerbox}
|
||||||
|
\end{qabox}
|
||||||
|
|
||||||
|
\section{后续规划}
|
||||||
|
|
||||||
|
\subsection{待完成事项}
|
||||||
|
\begin{itemize}
|
||||||
|
\item XXXX:填写待实现功能。
|
||||||
|
\item XXXX:填写待优化问题。
|
||||||
|
\item XXXX:填写预计完成时间。
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\subsection{版本记录}
|
||||||
|
\begin{table}[htbp]
|
||||||
|
\centering
|
||||||
|
\caption{版本记录}
|
||||||
|
\begin{tabular}{llll}
|
||||||
|
\toprule
|
||||||
|
\textbf{版本} & \textbf{日期} & \textbf{作者} & \textbf{修改内容} \\
|
||||||
|
\midrule
|
||||||
|
v1.0 & \today & XXXX & 创建基础文档 \\
|
||||||
|
\bottomrule
|
||||||
|
\end{tabular}
|
||||||
|
\end{table}
|
||||||
|
|
||||||
|
\end{document}
|
||||||
Reference in New Issue
Block a user