AMP(一)算法框架和判别器
AMP(一)算法框架和判别器这篇是看天工开源项目时顺手补的 AMP 笔记,但这一篇先不拆具体代码,只讲 AMP 原理 AMP,全称是 Adversarial Motion Priors。这名字看起来挺抽象,拆开以后其实就是:用对抗学习从 motion dataset 里学一个“运动先验”,然后把这个先验变成 style reward,和任务奖励一起给 PPO 用。 这里的核心不是让 policy 精确跟踪某一帧动作,而是让 policy 生成的状态转移整体看起来像动作数据集里的运动。 AMP 解决的核心痛点在 DeepMimic 这种方法里,一般会有一条明确的参考轨迹: \hat q_0,\hat q_1,\hat q_2,\ldots策略在当前 phase 下,去跟踪对应时刻的目标姿态。奖励通常是人工设计的: r_{\text{imit}} = w_p r_{\text{pose}} + w_v r_{\text{vel}} + w_e r_{\text{end-effector}} + \cdots这样做能把单条动作模仿得很好,但问题也很明显: · 必须知道当前该模仿哪...
摆线针轮减速器设计记录:原理与核心参数
摆线针轮减速器设计在本科刚开始接触三维建模的时候,尤其是高教杯这种建模比赛的时候,最容易出现的就是一类题目:减速器。那时候更多的是以传统齿轮为主的,比如行星齿轮,蜗轮蜗杆这些。然而在众多减速器中,有一种减速器他不在需要传统复杂的齿形加工,以一种非常巧妙的方式来传递里,他就是摆线针轮减速器,他凭借体积紧凑、传动比大、抗冲击承载能力强这些特点,在高扭矩密度场景里经常出现,比如四足机器人的关节、高精度伺服控制、一些小体积大扭矩执行器。还有一点就是,他不需要繁杂的齿形加工,我觉得他是最适合3D打印材料的减速器了。 这篇先不把所有齿廓细节都展开成完整工程校核,主要梳理摆线针轮减速器到底怎么转起来,以及设计初期必须先定下来的核心参数。 然后实物的话后续做完再更。 后续有时间再更谐波减速器,又是另一种机械仙品 一、前置原理一个圆绕三倍于其周长的一根木棒滚动,会转三圈。 把木棒弯成一个圆,然后一个小圆在外面绕着三倍于其周长的大圆滚动,会多转一圈,因为它不仅自己滚,还绕大圆公转了一圈,所以外滚时是四圈。 如果小圆是在大圆内部滚动,则会少一圈,所以是两圈。 这件事本质上就是:当小圆沿着大圆滚一圈时...
手撕PPO(三)多环境并行
PPO 第三版:多环境这次把 PPO 从“单个 Pendulum 环境一局一更新”的版本变成多环境并行,强化学习怎能不并行呢 1. 上一版的问题训练主循环大概是这样的: 12345只创建一个 `Pendulum-v1` 环境。每个 episode 跑最多 200 步。每一步让 Actor 采样一个动作。送进环境前,对动作做 `action.clip(ACTION_LOW, ACTION_HIGH)`。一局结束后,用这一条轨迹做一次 PPO update。 这个版本已经比最初版稳定,因为它至少避免了 Pendulum 收到非法动作。但它还有几个明显问题。 首先采样效率低。PPO 是 on-policy 算法,每次更新都必须先采新数据。上一版只跑一个环境,一局最多 200 个 transition,样本量小,更新频率高,噪声也比较大。想让训练更稳,要么攒更多 episode 再更新,要么同时跑多个环境。 其次动作边界处理还不够完善和通用。上一版 Actor 里确实用了 tanh,但它作用在 mean 上,而且是手动乘 2: 1mean = self.tanh(self.fc_mea...
Flipper Zero 二次开发记录
Flipper Zero 二次开发这篇主要记录一下 Flipper Zero 的二次开发流程。现在先不碰完整固件源码,主要基于三方优化系统 Momentum 做 External App,也就是最后生成 .fap 插件,放到 SD 卡里运行。 目前基于三方优化系统 Momentum 来进行学习,该系统被公认为目前三方里比较好用的一版。 一、上位机、固件和文件系统Windows 上位机安装。 本地安装包原来放的是: 1flipper zero电脑管理软件.exe 安装三方固件时,用的是 Momentum 的更新包: 1flipper-z-f7-update-mntm-dev-42630e91.tgz 这里不要再在文章里直接引用本机 Downloads 路径。博客部署之后读不到本地路径,所以只记录文件名,实际文件按自己的电脑位置导入即可。 文件系统大概长这样: 这里后面会用到的是 SD 卡里的 apps 目录。External App 编译出来之后,本质上就是把 .fap 文件放进对应分类目录,比如 apps/Tools。 二、开发环境先创建工作目录: 12mkdir Flipp...
手撕PPO(二)代码实现记录
PPO 代码实现记录(Pendulum)这篇是 train.py 和 agent.py 的实现记录,原理部分在 NOTE.md 里已经写过了,这里只记代码怎么搭起来的、每块在干嘛、哪里踩过坑。环境是 Pendulum-v1,连续动作、单环境,固定 200 步 truncate。先看 train.py 的主循环,再拆 agent.py 里 actor/critic/buffer/update 那几块。 后面加 advantage 标准化和梯度裁剪两个 trick 是因为一开始训不稳,跑到后面会崩,这部分单独放最后记。 一、train.py:主循环导包、建倒立摆环境先导包。gymnasium 给环境,torch 存模型,time/os 拼日志路径,matplotlib 最后画曲线。PPOAgent 和 device 从自己写的 agent.py 里拿,device 是 agent.py 里统一判好的 cuda/cpu。 建环境用 gym.make,Pendulum 的 reward 全是负的,立得越稳越接近 0,所以 0 是上限。 123456789import gymnasium...
手撕PPO(一)论文框架
这份笔记是为了复现 PPO 整理的,按照采样、优势估计、损失计算、参数更新的顺序走一遍。公式记号尽量和 Schulman 的两篇原文(PPO 2017、GAE 2015)保持一致。这篇文章主要记 PPO 论文和实现里容易对不上的地方,代码复现部分下一篇再讲。 原论文链接: [1707.06347] Proximal Policy Optimization Algorithms 前置知识原本的策略梯度DQN 是学一个“动作价值函数” $Q(s,a)$,然后选 $Q$ 最大的动作。Policy Gradient 是直接学一个策略 $\pi_\theta(a \mid s)$,让网络直接输出动作概率,或者输出连续动作分布的参数。 DQN 里网络做的是:输入 state,输出每个动作的 $Q$。训练目标是让 $Q$ 满足 Bellman 方程: Q(s,a) \approx r + \gamma \max_{a'} Q(s', a')所以 DQN 本质上是: 先学“每个动作有多好”。 再根据 $Q$ 值选动作。 Policy Gradient 的思路Policy Gradient ...
CPP树
\theta=5description和keywords都是给爬虫看的 map myMap键值对,键唯一,按照键的大小自动排序 12345678910111213//插入,访问,查找,删除myMap.insert(make_pair(1, 100)) #make_pair打包键值对myMap[2] = 200;myMap.insert({{3, 300}, {4, 400}}); auto it = myMap.find(3);if (it != myMap.end()) { a= it->first; b= it->second ;} else {}myMap.erase(1); str.size()获取列表长度 string定义字符串 unordered_map:适合对元素顺序没有要求,且需要快速访问的场景,尤其是在元素数量较多且频繁进行查找、插入和删除操作时。 .push_back(),在vector后面添加元素 vector
贪心算法
分发饼干大饼干优先给大胃口的学生,遍历学生,满足条件后再更新饼干 摆动序列多种情况,记录上一个对差值,遇到平坡不更新差值,只在变化时更新差值(last带等号,now不带等号) 最大子序和当当前值为负数的时候,放弃掉当前值,重新开始,因为负数加上任意一个数都会更小int result = INT32_MIN;表示32位有符号整数的最小值 买股票的最佳时机II只计算上升段的和写法优化:大于0,+=value:+=max(value,0); 1result += max(prices[i] - prices[i - 1], 0); 跳跃游戏最大覆盖值,一直更新for循环的限制值,只在限制值范围内循环,找到答案提前return 跳跃游戏II(重做没思路)在当前覆盖范围内,找最大的跳跃距离 K次取反后最大化数组和先尽量吧负数全变成正数,再针对最小的数疯狂取反代码优化:cmp排序: 1234static bool cmp(int a, int b) {return abs(a) > abs(b);}sort(A.begin(), A.end(), cmp...
Legged gym 使用笔记
Legged gym 使用笔记入门案例1.倒立摆 首先在 envs 目录下创建自己的环境 cartpole。 这篇主要是看自定义 Cartpole2Task 环境时做的源码笔记。整体流程大致是这样: 在 envs 目录下放自己的任务代码和 config,比如 cartpole2.py、cartpole2_config.py。 在 envs/__init__.py 中注册任务名、环境类、环境配置和 PPO 配置。训练脚本通过任务名找到对应环境。 环境类继承 BaseTask,核心是实现仿真创建、step、reset、reward、observation 这些函数。 初始化时先解析配置,再调用父类创建 sim/env,随后初始化 PyTorch buffer,最后准备奖励函数列表。 训练时算法会不断调用 env.step(actions)。一次 step 里先裁剪 action,再计算 torque,接着推进物理仿真,刷新状态,然后检查终止条件,计算奖励,重置需要结束的环境,最后重新计算 observation 并返回给算法。 下面按函数继续记录。 导入LEGGED_G...
FreeRTOS中断管理
中断是 MCU 的硬件机制。STM32 通过 NVIC 管理外设中断,每个中断对应一个中断服务例程,也就是 ISR。以 STM32F4 这类 Cortex-M4 为例,中断优先级数字越小,硬件优先级越高;数字越大,硬件优先级越低。 FreeRTOS 运行以后,任务调度和中断并不是两套互不相关的东西。任务切换依赖 SysTick、PendSV 这些异常,中断里也经常需要释放信号量、写队列、发送任务通知,把外设事件交给任务处理。因此中断优先级和 FreeRTOS API 的调用规则需要先明确。 一、STM32 中断优先级STM32 的中断由 NVIC 管理。优先级通常分成抢占优先级和子优先级,抢占优先级决定能不能互相嵌套,子优先级用于同抢占优先级下的响应顺序。 在 FreeRTOS 工程里,一般会把优先级分组配置成所有有效位都用于抢占优先级,比如 STM32 HAL 里常见的 NVIC_PRIORITYGROUP_4。这样 FreeRTOS 用 BASEPRI 屏蔽中断时,判断逻辑比较直接。以 STM32F4 常见的 4 个有效优先级位为例,中断优先级数值范围是 0 到 15,其中 ...









