从R2S2到OpenWBT——提高人形的到达能力:模仿教师策略下RL探索新行为,最终实现技能之间的协调与切换

前言

如此文《KungfuBot——基于物理约束和自适应运动追踪的人形全身控制PBHC,用于学习打拳或跳舞(即RL下的动作模仿和运控)》的前言所说

昨天618,我司「七月在线」长沙具身团队那边,以同事朝阳为主力,我打杂,折腾了整整一天,终于可以通过VR摇操宇树G1了——当然,摇操是为了做训练数据的采集,从而方便 下一步的模型(策略)训练,最终实现机器人自主做各种任务


然灵巧手还没到货(顺带吐槽一下,现在的灵巧手都太贵了,有没有性价比高的或者合作呢,如有,欢迎私我),临时再打印个二指夹爪也得等

那未来这几天 搞啥呢?那就搞运动吧,如此,便关注到最新出来的三个工作

  1. 第一个是GMT: General Motion Tracking forHumanoid Whole-Body Control
  2. 第二个是R2S2和OpenWBT
  3. 第三个则是本文要解读的KungfuBot

本文则来解读上面的第二个工作:R2S2和OpenWBT

第一部分 Real-world-Ready Skill Space(R2 S2)

1.1 引言与相关工作

1.1.1 引言

如R2S2原论文所说

  • 传统的基于模型的控制方法[3,4,5,6,7,8,9,10,11,12,13]难以应对系统建模中的固有不完善性和环境扰动
  • 近年来,端到端强化学习在类人机器人全身控制任务中取得了显著进展[14,15,16,17,18,19,20,21,22]
    作者想,是否可以利用该方法赋予类人机器人完成需要人类级大可达空间的任务能力?
  • 他们发现,对于如此复杂的全身控制(WBC)问题,优化难度和仿真到现实(sim2real)不稳定性是主要挑战。如前所述,释放类人机器人到达潜力需要多种技能的协同——而完全从零学习非常困难

    此外,稳定的现实世界表现通常需要在训练过程中施加针对具体技能的约束。然而,在这种多技能设置下,以端到端强化学习方式施加足够的行为约束极具挑战性,因为不同技能可能需要不同的约束,且这些约束之间可能相互冲突

对此,来自的研究者们提出了Real-world-Ready Skill Space(R2 S2),旨在构建一个涵盖并编码多种现实世界可用运动技能的技能空间。所学习的空间可以作为结构化技能先验,并有助于以高效且可从仿真到现实迁移的方式执行任务

具体而言

  1. 他们首先构建了一个共享且易于定义的原始技能库
    在本研究中,这些技能包括运动身体姿态调整(如改变身体高度、弯腰),以及手部到达目标的能力
    通过对每项技能单独调优和仿真到现实(sim2real)评估,确保其最佳性能和稳健的仿真到现实迁移
  2. 尽管分离的原始技能已具备现实世界应用能力,但它们作为实际技能空间仍存在两点不足:
    1)由于原始技能的独立训练,不同技能之间的协调(例如上半身伸手取物与下半身下蹲同步)、切换(如下半身从运动到姿态调整)属于分布外情况,导致技能空间在实际应用中不完整;
    2)分离的技能往往具有不一致的任务空间,缺乏为高层规划器提供统一表达的能力

    因此,他们引入了一个额外阶段,将不同技能进行集成(不仅学习各项技能本身,还学习它们之间的协调与切换),并对技能表示进行编码

最终,他们通过结合模仿学习(IL)和强化学习(RL),以变分信息瓶颈训练学生策略,并将预先构建的技能库作为教师策略

  • 通过
    \rightarrow  模仿学习,学生策略可以从教师策略中继承具备现实世界应用能力的技能先验
    \rightarrow  强化学习则进一步提升学生策略在协调与切换技能方面的能力,这是教师策略所不具备的。学生网络采用编码器-解码器结构,并结合变分信息瓶颈,以建模基于本体感觉的运动技能分布
  • 最后,训练任务特定的高层规划策略,从这一具备现实世界应用能力的技能空间中采样潜在编码,从而稳定地完成现实世界中的目标到达任务

1.1.2 相关工作

首先,对于人形机器人学习

  1. 强化学习(RL)策略在近期仿人机器人学习领域取得了巨大进展。行走方面的研究[23,24,25,26,27,28,29,30,31]旨在赋予双足仿人机器人在不同地形上稳定且灵活行走的能力
    然而,这些研究往往只关注仿人机器人的下半身,忽视了其全身的到达和交互潜力
  2. 基于学习的仿人机器人全身控制方法[14,15,16,17,19,20,32,33,34,35]最近展现了新的能力,推动了仿人机器人技术的边界
  3. 数据驱动的运动追踪方法[14,15,32,19,20,33,34]能够生动地模仿人类动作,从而实现人机远程操作
    Zhang等人[16]将仿人机器人全身控制表述为一系列顺序接触,并提出了一种基于接触的全身控制(WBC)框架

然而,现有研究要么仅在相对中性的身体姿态下工作[16,17],要么缺乏实现实际任务所需的规划模块[35]。如何让仿人机器人具备接近人类水平的目标到达能力,仍然鲜有深入探索

对于,对于技能空间学习

  1. 在基于物理的角色动画中,技能空间[36,37,38,39,40,41,42,43,44,45,46]通常通过学习来复用来自动作捕捉数据集的运动先验
    动作模仿[37,39,40,41,42,46,47]或对抗式学习[36,43,44,45]被用于构建技能潜在空间,随后采样的潜在变量可以通过解码器转化为动作
  2. 对于高层次任务,任务特定的规划器会被学习,以便从预先构建的潜在空间中复用技能,从而更高效且自然地完成任务

    尽管技能空间学习在基于物理的角色动画中取得了巨大成功[38,48,49],但将这种范式迁移到现实世界的人形机器人面临挑战,主要原因在于高质量人形机器人动作数据集的缺乏以及仿真到现实(sim2real)的难题

与这些工作不同,作者是从经过仿真到现实评估(可直接应用于现实世界)的原始技能中学习技能空间,而非依赖动作捕捉数据,以提升现实世界的稳定性

1.2 释放人形在真实世界环境下的到达潜力:面向实际应用的技能空间

在本节中,作者描述了如何学习一个面向现实世界的技能空间(R2 S2),并利用它以稳定且可迁移的sim2real 方式支持实际的目标达成任务

  1. 首先,作者构建了一个由n 个共享且易于定义的基于强化学习的原始技能库\left\{\pi_{1}^{\text {prim }}, \ldots, \pi_{n}^{\text {prim }}\right\},每个技能\pi_{i}^{\text {prim }}都经过单独调优和sim2real 评估(具备现实世界可用性)
  2. 然后,将通过结合模仿学习和强化学习,将这些技能集成并编码为一个具有潜在技能z 空间的集成学生策略\pi^{\text {ensem }}
    所学习的技能空间涵盖了多种面向现实世界的运动技能 作为一种技能先验,并以可从仿真到现实迁移的方式辅助任务执行
  3. 在学习到的技能z 空间中,高层规划器\pi^{\text {plan }} 被训练用于采样潜在技能以完成实际任务
    该流程如图2 所示

    1)将复杂的WBC运动技能分解为原始技能库,每个原始技能都经过单独调优和仿真到现实的评估
    2)通过变分信息瓶颈将多个原始技能集成为学生策略
    3)训练高层规划策略,从R2S2中采样,以高效且稳定地完成真实世界的目标达成任务

    此外,所有策略训练中使用PPO [50],采用域随机化进行仿真到现实的迁移,并在Isaac Gym[51] 中进行仿真

1.2.1 原始技能库

为了释放人形机器人到达潜力,作者将原始技能库\left\{\pi_{1}^{\text {prim }}, \ldots, \pi_{n}^{\text {prim }}\right\}设计为包括行走、身体姿态调整(改变身体高度、弯腰)和手部到达。每项技能都被单独调优并经过sim2real评估,以最大化其能力和现实世界中的稳定性

原始技能可以被视为目标条件强化学习策略\pi^{\text {prim }}: \mathcal{G}^{\text {prim }} \times \mathcal{S}^{\text {prim }} \mapsto \mathcal{A}^{\text {prim }},其中

  • \mathcal{G}^{\text {prim }}包含指定技能目标的目标命令g_{t}
  • \mathcal{S}^{\text {prim }} 包含机器人在每个时间步t 的本体感知观测和历史动作信息s_{t}=\left[\omega_{t}, g r_{t}, q_{t}, \dot{q}_{t}, a_{t-1}\right],其中\omega_{t}, g r_{t}, q_{t}, \dot{q}_{t}, a_{t-1}分别表示在基坐标系下的角速度、投影重力、身体部位自由度位置、身体部位自由度速度、上一帧的低层动作

    值得注意的是,对于q_{t}, \dot{q}_{t}, a_{t-1},每个策略仅以相关身体部位的信息作为不同技能的观测
  • \mathcal{A}^{\text {prim }}包含机器人身体部位动作(PD 目标)a^{\text {prim }},该动作被输入到PD 控制器用于力矩计算
    a^{\text {prim }} 仅控制每项技能对应的身体部位,其他关节保持固定

它们的训练奖励可以写为

r_{\text {prim }}=r_{\text {command }}+r_{\text {behavior }}+r_{\text {regularization }}

其中

  • r_{\text {task }} 表示技能指令的跟踪目标
  • r_{\text {behavior }} 描述了特定技能的行为约束,以保证sim2real 的稳定性
  • r_{\text {regularization }} 是与技能无关的正则化项

在接下来的章节中,主要介绍每个技能的 r_{\text {behavior }},因为它们对于每项技能的 sim2real 迁移至关重要。关于奖励设计的更多细节,请参考附录

首先,关于运动控制

  1. 为了实现运动控制
    \mathcal{G}^{\text {loco }}=\left\langle v_{x}^{\mathrm{c}}, v_{y}^{\mathrm{c}}, \omega^{\mathrm{c}}\right\rangle使人形机器人能够跟踪机器人基座在机器人基座坐标系下的期望线速度和角速度
  2. 为了约束运动行为并复现类人的双足步态,他们将每只脚的运动建模为交替的摆动和支撑相位序列,并引入了一种受[31, 52] 启发的周期性奖励框架

    其中,C_{\text {foot }}(t)服从Von Mises 分布,t \in[0,1)是一个随时间变化的相位变量,在归一化时间内周期性循环

其次,对于身体姿态调整

\mathcal{G}^{\text {body }}=\left\langle h^{\mathrm{c}}, p^{\mathrm{c}}\right\rangle在全局坐标系中跟踪基准高度和俯仰角
作者发现,对于这样的技能,运动学和动力学的对称性对于实际环境中的稳定性非常重要,因此他们引入了

rbase_roll和rleg_pos旨在实现运动学对称性

  • rbase_roll用于惩罚机器人底座的滚转旋转,以防止类人机器人倾倒
  • rleg_pos用于惩罚双腿配对关节自由度位置的不对称

rleg_torque和rtouch_ground旨在实现动态平衡

  • rleg_torque鼓励配对下肢关节输出相同的力矩
  • rtouchg_round鼓励双脚同时与地面接触

最后,对于手部到达

\mathcal{G}^{\text {hand }}=\left\langle e^{\mathrm{c}}\right\rangle跟踪机器人本地坐标系中的目标末端执行器6D 位姿。手臂对于sim2real 部署来说相对容易,因此我们没有专门为该技能设计任何r_{\text {behavior }}

1.2.2 面向现实世界的技能空间

给定现实世界可用的原始技能\left\{\pi_{1}^{\text {prim }}, \ldots, \pi_{n}^{\text {prim }}\right\},直接尝试在它们各自的主要任务空间中复用这些原始技能来完成不同任务是一种直接的规划方式。但实际上,这些技能不足以作为一个实用的技能空间

  1. 由于分开训练,原始技能彼此之间是不可见的。不同技能之间的协调(例如,上半身在够取物体的同时下半身在下蹲)、切换(例如,下半身从行走切换到身体姿态调整)属于分布外问题
  2. 简单地将不同身体部位的动作拼接,或从行走技能切换到身体姿态调整技能,会导致不稳定,甚至可能导致机器人摔倒。如果没有无缝的协调和切换,技能空间对于实际任务的完成而言就是不完整的
  3. 此外,原始技能的不匹配任务空间(在作者的设定中,行走对应v_{x}^{\mathrm{c}}, v_{y}^{\mathrm{c}}, \omega^{\mathrm{c}},身体姿态调整对应h^{\mathrm{c}}, p^{\mathrm{c}},手部到达对应e^{\mathrm{c}})对于高层规划来说是低效的

为了解决这些问题,作者提出训练一个集成学生策略\pi^{\text {ensem }}\left(a_{t} \mid s_{t}, g_{t}\right),并使用变分信息瓶颈来集成不同的技能。” 集成” 不仅意味着模仿不同的原始技能,还包括学习它们的协调与切换。在技能集成过程中,不同的技能被编码到一个潜在技能z 空间中,然后解码为各关节的动作

首先,通过模仿学习和强化学习实现技能集成

在线模仿学习方法『例如,DAgger [53-A reduction of imitation learning and structured prediction
to no-regret online learning]
』通常用于从教师策略向学生策略进行技能蒸馏。然而,仅依赖模仿学习无法为学生策略提供超越教师策略的新能力(如不同技能之间的协作与切换)

因此,作者提出将模仿学习和强化学习结合,通过将IL 损失和RL 损失相加来实现

  1. 在作者的设定中,IL-即DAgger从多个教师策略中蒸馏出具备真实世界适应性的技能先验。在此基础上,RL(即作者设定中的PPO)进一步鼓励策略学习新的行为,以实现无缝的技能切换与协作
  2. 与训练分离的原始技能不同,作者在训练环境中进行了两方面的修改:
    \rightarrow  同时为不同身体部位发送目标指令(例如,策略需要在行走的同时跟踪目标手的6D 姿态),以建模技能协作
    \rightarrow  允许某一身体部位的技能在一个episode中从一种切换到另一种,以建模技能切换

形式化地,在每个时间步t ,两种原始技能\left\{\pi_{t}^{\text {lower }}, \pi_{t}^{\text {upper }}\right\},其中

  • \pi_{t}^{\text {lower }} \in\left\{\pi^{\text {loco }}, \pi^{\text {body }}\right\} },是下半身的教师策略
  • \pi_{t}^{\text {upper }} \in\left\{\pi^{\text {hand }}\right\},是上半身的教师策略

学生策略目标g_{t} 中包含一个技能指示器,用于指示当前激活的是哪一个教师策略。当发生(技能)切换(如下半身从运动到姿态调整)时,令\pi_{t+1}^{\text {lower }} \neq \pi_{t}^{\text {lower }}。通过这种方式,所有不同技能之间的协作与切换都被包含在学生策略中

奖励函数可写为

\mathcal{L}_{\text {Ensem }}=\lambda_{1} \mathcal{L}_{\text {DAgger }}+\lambda_{2} \mathcal{L}_{\text {PPO }}

其中,λ1 逐渐从0.95 降低到0.05,而λ2 则相应地反向调整

该设计鼓励学生策略首先模仿教师策略,随后再探索新行为。作者令

\mathcal{L}_{\text {DAgger }}=\mathbb{E}_{\left(s, a^{*}\right) \sim \mathcal{D}_{\text {agg }}}\left[\left\|a_{t}^{\text {ensem }}-a_{t}^{*}\right\|^{2}\right]

其中,a_{t}^{\text {ensem }}\pi^{\text {ensem }} 的输出动作,a_{t}^{*}=\operatorname{concat}\left(a_{t}^{\text {lower }}, a_{t}^{\text {upper }}\right)是来自下半身和上半身教师策略的动作组合

  1. 对于\mathcal{L}_{\mathrm{PPO}},作者仅仅将\pi_{t}^{\text {lower }}\pi_{t}^{\text {upper }}在基础技能训练阶段定义的奖励项进行合并。作者发现,学生策略能够在没有任何额外奖励项的情况下成功学习协调和转换技能
  2. 虽然协调和转换是在此阶段新学到的,但从教师策略中继承的技能先验起到了良好的热身作用,并使得新能力具备sim2real 的可迁移性

其次,学习面向真实世界的技能空间作为潜在表示

虽然学生策略可以集成多种原始技能,但由于缺乏统一的技能表示,不匹配的技能空间阻碍了高效的高层规划

为了解决这一问题,作者采用了带有条件变分信息瓶颈的编码器-解码器框架

  • 使用变分编码器\mathcal{E}\left(z_{t} \mid s_{t}, g_{t}\right)=\mathcal{N}\left(z_{t} ; \mu^{e}\left(s_{t}, g_{t}\right), \sigma^{e}\left(s_{t}, g_{t}\right)\right)对当前状态和目标进行条件建模,以获得潜在编码
  • 相应的解码器\mathcal{D}\left(a_{t} \mid s_{t}, z_{t}\right)将采样得到的潜在编码映射为以条件为基础的动作状态

受[40] 的启发,作者引入了一个可学习的条件先验\mathcal{P}\left(z_{t} \mid s_{t}\right)=\mathcal{N}\left(z_{t} ; \mu^{p}\left(s_{t}\right), \sigma^{p}\left(s_{t}\right)\right),用于捕捉基于状态的动作分布,而不是在潜在空间上假设一个固定的单峰高斯结构,因为机器人在不同状态下的动作分布应当有显著差异

因此,集成学生策略可以被表述为\pi^{\mathrm{ensem}} \triangleq(\mathcal{E}, \mathcal{D}, \mathcal{P})。训练\pi^{\text {ensem }} 时的总损失可以表示为

\mathcal{L}_{\text {Total }}=\mathcal{L}_{\text {Ensem }}+\lambda_{3} \mathcal{L}_{\text {Regu }}+\lambda_{4} \mathcal{L}_{\mathrm{KL}}

\mathcal{L}_{\text {Regu }}=\left\|\mu^{e}\left(s_{t}, g_{t}\right)-\mu^{e}\left(s_{t+1}, g_{t+1}\right)\right\|

鼓励连续潜在编码之间的时序一致性,并使技能空间更加结构化。\mathcal{L}_{\mathrm{KL}}=D_{\mathrm{KL}}\left(\mathcal{E}\left(z_{t} \mid s_{t}, g_{t}\right) \| \mathcal{P}\left(z_{t} \mid s_{t}\right)\right)鼓励潜在编码的分布接近可学习的先验分布

1.2.3 面向现实世界的技能空间中的高层规划

在已学习的潜在技能空间基础上,作者训练特定任务的高层规划器\pi^{\text {plan }}\left(z_{t} \mid s_{t}^{\text {high }}, g_{t}^{\text {high }}\right),以为不同的目标达成任务选择潜在技能嵌入

\pi^{\text {plan }} 的动作现在处于潜在空间z_{t}中。采样得到的z_{t} 通过冻结的解码器\mathcal{D} 解码为各关节动作a_{t}

训练奖励可以写为

r_{\text {plan }}=r_{\text {task }}+r_{\text {regularization }}

其中r_{\text {task }}是任务执行目标,r_{\text {regularization }} 是在技能库构建阶段引入的与技能无关的正则化奖励。我们发现复用r_{\text {regularization }}可以增强动作的稳定性。关于高层规划器训练的更多细节,请参见附录

1.3 实验

在本节中,作者将在仿真和现实环境中进行全面实验,以回答以下问题:

  1. Q1.Real-world-Ready Skill Space(R2 S2)能否释放人形机器人到达的潜力?
  2. Q2.R2 S2 如何帮助释放人形机器人到达的潜力?他们在Unitree H1 上进行了所有实验

1.3.1 仿人机器人可达空间:实验设置、实验指标、基线方法、实验结果

  • 对于实验设置
    作者将类人机器人到达问题定义为:给定一个目标到达状态\left[x y \omega_{\text {root }}, x y z_{\text {hand }}\right],判断类人机器人是否能够成功实现该状态
    其中,x y \omega_{\text {root }}表示机器人根部的水平位置和朝向,x y z_{\text {hand }}是在x y \omega_{\text {root }}固定时手部能够到达的3D 位置

    由于大多数现有方法都具备全向运动能力,已经能够满足在平面地面上的任意x y \omega_{\text {root }} ,因此作者主要比较对于任意给定x y z_{\text {hand }} 的实现能力
  • 对于实验指标
    作者使用可达x y z_{\text {hand }}空间来衡量人形机器人到达能力。作者通过计算以肩关节为中心、手臂长度为半径的球体所扫过的体积,粗略估算可达空间
    虽然这种计算方法并不完全精确,但它能够根据身体姿态参数方便地估算可达x y z_{\text {hand }}空间
  • 对于基线方法
    如何释放人形机器人到达能力的潜力尚未被充分研究,相关工作较少。他们主要将他们的方法与两项近期在相同硬件(Unitree H1)上聚焦于全身控制的工作进行对比
    \rightarrow  ExBody[14]。该方法将运动目标解耦为移动目标和表达目标,其中移动目标包括对机器人底盘的指令,如速度、横滚、俯仰和底盘高度
    他们在仿真中复现了该方法,并将其部署到他们的硬件上
    \rightarrow  HUGWBC[28]。本研究提出了一种统一的全身控制器,能够生成多样化的运动方式并调整身体姿态。由于代码未公开,他们根据其原论文中的姿态调整参数计算可达空间

// 待更

第二部分 OpenWBT

// 待更

<think>好的,我现在需要帮助用户了解或实现得物签名的相关技术,特别是签名算法的实现方式。首先,我需要收集已有的信息。根据用户提供的引用,特别是引用[4]和[5],得物的签名算法可能涉及逆向工程分析,使用了JavaScript中的XMLHttpRequest重写来拦截请求,并在请求中包含特定的sign参数。这可能意味着签名生成是在客户端进行的,通常在前端JavaScript代码中完成。 接下来,我应该考虑常见的签名生成方法。常见的Web应用签名算法通常使用HMAC、AES、RSA或自定义的哈希组合。引用[1]提到了RSA算法,但得物的签名可能更倾向于使用HMAC-SHA256之类的哈希算法,结合时间戳、随机数和请求参数进行签名,以防止篡改和重放攻击。 用户可能需要具体的步骤,比如逆向分析得物的JavaScript代码,找到生成sign的函数,提取关键参数和加密逻辑。引用[5]中的代码片段展示了如何重写XMLHttpRequest的open方法来拦截请求,这可能用于调试和定位签名生成的代码位置。 此外,引用[4]提到使用Python进行算法还原,所以可能需要在Python中复现JavaScript的签名生成逻辑。这通常涉及分析请求参数如何排序、拼接,以及如何密钥结合进行哈希或加密。需要注意反爬机制,如obfuscation(代码混淆)或动态密钥,这可能需要使用AST(抽象语法树)解析或动态执行来还原算法。 用户可能还需要了解如何应对反调试措施,比如在Chrome开发者工具中使用断点调试,或者使用工具如Frida进行Hook。同时,引用[3]和[4]强调了法律和合规问题,确保研究仅用于学习目的,不用于非法用途。 最后,应该提醒用户注意法律风险,遵循网站的使用条款,避免侵犯知识产权或违反计算机安全法律。总结起来,实现得物签名需要逆向工程分析前端代码,提取关键算法,处理可能的混淆和反调试,最后用目标语言如Python复现算法。</think>### 得物签名算法实现方式分析 得物签名算法主要用于接口请求的身份验证和防篡改保护,常见实现方式涉及以下技术点: #### 1. **签名参数组成** 签名通常由以下参数动态生成: - 请求参数(经排序、过滤空值后拼接) - 时间戳(如:$timestamp=1620000000$) - 随机数(如:$nonce=5a8s3d$) - 设备指纹(如:$device\_id=abcdef$) - 应用密钥(加密盐值,可能动态获取)[^4] 示例参数拼接逻辑: $$ \text{sign\_str} = \text{path} + \text{sorted\_params} + \text{timestamp} + \text{nonce} $$ #### 2. **加密算法类型** 根据逆向分析,得物可能采用以下组合: - **HMAC-SHA256**:对拼接字符串进行哈希运算 - **AES/Base64编码**:对结果二次处理 - **自定义位移/异或操作**:增加逆向难度[^5] #### 3. **JavaScript代码混淆** 关键函数可能被混淆,例如: ```javascript function _0x12ab5(a, b) { return a ^ b << 3; } // 需要AST解析还原控制流 ``` #### 4. **Python算法还原示例** ```python import hmac import hashlib def generate_sign(params, secret_key): # 1. 参数排序并拼接 sorted_str = '&'.join([f"{k}={v}" for k,v in sorted(params.items())]) # 2. HMAC-SHA256加密 sign = hmac.new(secret_key.encode(), sorted_str.encode(), hashlib.sha256).hexdigest() # 3. 自定义处理(示例) return sign.upper() + str(int(time.time())) ``` #### 5. **反爬对抗措施** - 动态密钥:通过接口定期更加密盐值 - 环境检测:验证是否在真机环境运行 - 请求频率限制:异常高频触发验证码[^5]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

v_JULY_v

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值