【05.isaac-lab】最新从零无死角系列-(06) isaac-lab之框架剖析:参数解析与加载, Hydra 配置详解与代码分析

若需观看机器人系列相关博客,请劳驾至:【足式机器人无死角系列之-【强化学习基础-通用】、【仿真及训练环境】、【强化学习】:isaac-gym 与 isaac-lab 从零开始

郑重声明:该系列博客为本人 ( W e n h a i Z h u ) 独家私有 , 禁止转载与抄袭 , 首次举报有谢 , 若有需请私信授权! \color{red}郑重声明:该系列博客为本人(WenhaiZhu)独家私有,禁止转载与抄袭,首次举报有谢,若有需请私信授权! 郑重声明:该系列博客为本人(WenhaiZhu)独家私有,禁止转载与抄袭,首次举报有谢,若有需请私信授权!

本系列博客链接为: {\color{blue}本系列博客链接为:} 本系列博客链接为:【05.issac-lab】最新从零无死角系列-(00) 目录最新无死角源码讲解:https://blog.csdn.net/weixin_43013761/article/details/143084425

上一篇博客对包装器进行较为详细的概念介绍,且细致分析视屏录制包装器(gym.wrappers.RecordVideo)以及强化学库包装器(RslRlVecEnvWrapper)相关代码,得知 [境与强化学习库,或者强化学习算法是如何联系到一起的]。

         ...... ......已分析
         2: 掌握训练过程的总体流程(以任务为导向)。
         3: 环境与强化学习库,或者强化学习算法是如何联系到一起的?。
        4:文件配置是如何加载解析的,如搭建个人项目应该如何进行文件配置? --> 该篇博客
        5: 如何训练自定义智能体,且使训练过收敛。
        6: ......待定

注意:如果有提示大家,[大致过一遍即可,不用在意细节] 的地方,就不要钻牛角尖,快速阅读一下即可,后面会回过来百分百的进行详细分析。

本博客编写于: 20250111 ,台式机为 u b u n t u 20.04 , 3090 G e F o r c e R T X 显存 24 G { \color{purple} 本博客编写于:20250111,台式机为 ubuntu 20.04,3090 GeForce RTX 显存24G} 本博客编写于:20250111,台式机为ubuntu20.043090GeForceRTX显存24G:与你现在的代码,或者环境等存在一定差异也在情理之中,故切勿认为该系列博客绝对正确,且百密必有一疏,若发现错误处,恳请各位读者直接指出,本人会尽快进行整改,尽量使得后面的读者少踩坑,评论部分我会进行记录与感谢,只有这样,该系列博客才能成为精品,这里先拜谢各位朋友了。

文末正下方中心提供了本人 联系方式, 点击本人照片即可显示 W X → 官方认证,请备注 强化学习 。 {\color{blue}{文末正下方中心}提供了本人 \color{red} 联系方式,\color{blue}点击本人照片即可显示WX→官方认证,请备注\color{red} 强化学习}。 文末正下方中心提供了本人联系方式,点击本人照片即可显示WX官方认证,请备注强化学习

一、前言

该篇博客主要对 isaac-lab 的参数解析与加载, Hydra 配置进行分析。其是该部分内容在前面的博客也有涉及,如 Hydra 于 【05.issa-lab】最新从零无死角系列-(03) isaac-lab之框架剖析,Omniverse、Isaac-sim 、Isaac-lab 对比,任务流程,Hydra 配置,强化学习库比较 中有简单介绍,不过只说明了使用方法,并没有介绍其具体实现的,不过没有关系,该篇博客会对相关源码进行分析。

前面博客训练的时候,执行了指令:

# 训练
python scripts/reinforcement_learning/rsl_rl/train.py --task Isaac-Velocity-Rough-Unitree-Go2-v0 --headless  --video --video_length 1000 --video_interval 5000

其中最重要的参数就是 Isaac-Velocity-Rough-Unitree-Go2-v0,若在源码中进行搜索,可以于 source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/go2/_init_.py 文件中看到类似如下代码:

gym.register(
    id="Isaac-Velocity-Rough-Unitree-Go2-v0", # 任务名称
    entry_point="isaaclab.envs:ManagerBasedRLEnv", # 环境实例类名
    disable_env_checker=True, # 是否禁用环境检查器
    kwargs={
        "env_cfg_entry_point": f"{__name__}.rough_env_cfg:UnitreeGo2RoughEnvCfg", # 环境类实例对应的配置文件
        "rsl_rl_cfg_entry_point": f"{agents.__name__}.rsl_rl_ppo_cfg:UnitreeGo2RoughPPORunnerCfg", # RSL-RL强化学习库算法配置文件
        "skrl_cfg_entry_point": f"{agents.__name__}:skrl_rough_ppo_cfg.yaml", # SKRL强化学习库算法配置文件
    },
)

其表达含义也是比较好理解的,若是训练指令设置 --task 参数为 Isaac-Velocity-Rough-Unitree-Go2-v0,则会构建 isaaclab.envs:ManagerBasedRLEnv 实例,其具体使用那个配置文件构建该实例,还得看一下运行训练的指令,如下:

# rsl_rl, 则表示使用配置类 f"{agents.__name__}.rsl_rl_ppo_cfg:UnitreeGo2RoughPPORunnerCfg"
python scripts/reinforcement_learning/rsl_rl/train.py --task Isaac-Velocity-Rough-Unitree-Go2-v0 --headless 

# skrl,则表示使用配置类 f"{agents.__name__}:skrl_rough_ppo_cfg.yaml"
python scripts/reinforcement_learning/skrl/train.py --task Isaac-Velocity-Rough-Unitree-Go2-v0 --headless 

那么这些配置文件在哪里呢?其实也比较好找,比如说使用 rsl_rl 进行训练,可在源码中搜 UnitreeGo2RoughPPORunnerCfg,易知该类实现于 source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/go2/agents/rsl_rl_ppo_cfg.py。其也就是使用:

python scripts/reinforcement_learning/rsl_rl/train.py --task Isaac-Velocity-Rough-Unitree-Go2-v0 

指令进行训练对应的配置文件了,可以看到配置文件中主要实现一个类,类中包含了各种配置参数,关于配置参数作用与注释后面再进行分析。先来看看配置文件时如何加载的。

二、配置文件

通过上面的分析,可以知道配置文件中的类 UnitreeGo2RoughEnvCfg 会被环境类 ManagerBasedRLEnv 使用到,但是具体是如何使用的呢?或者说配置文件是被如何加载的?这个问题依旧得回到 scripts/reinforcement_learning/rsl_rl/train.py 这个训练启动脚本来分析。该文件首先调用的就是 main() 函数,这是一个比较常规的操作,不过该函数的实现比较特别,其实用到了一个装饰函数,代码如下:

@hydra_task_config(args_cli.task, "rsl_rl_cfg_entry_point")
def main(env_cfg: ManagerBasedRLEnvCfg | DirectRLEnvCfg | DirectMARLEnvCfg, agent_cfg: RslRlOnPolicyRunnerCfg):

显然这个装饰函数就是 @hydra_task_config(), 其接收两个参数,第一个参数为训练任务名称(id), 比如前面提到的 id=“Isaac-Velocity-Rough-Unitree-Go2-v0”,第二个参数是配置文件的入口函数名,这里就是 “rsl_rl_cfg_entry_point”: f"{agents.name}.rsl_rl_ppo_cfg:UnitreeGo2RoughPPORunnerCfg"。前面提到,若使用 rsl_rl 需要运行 scripts/reinforcement_learning/rsl_rl/train.py 脚本,其原因就在这里,该装饰函数第二参数,即配置类对应的 key 值其是固定的。下面就来看看 @hydra_task_config() 接收这两个参数之后做了些什么。

大致过一遍即可,不用在意细节: \color{blue}大致过一遍即可,不用在意细节: 大致过一遍即可,不用在意细节: 首先 @hydra_task_config() 实现于文件 source/isaaclab_tasks/isaaclab_tasks/utils/hydra.py 之中, 这里先给出代码注释:

def hydra_task_config(task_name: str, agent_cfg_entry_point: str) -> Callable:
    """Decorator to handle the Hydra configuration for a task, 这个装饰器用于处理任务的Hydra配置

    This decorator registers the task to Hydra and updates the environment and agent configurations from Hydra parsed
    command line arguments, 这个装饰器注册任务到Hydra, 并从Hydra解析的命令行参数更新环境配置和智能体配置

    Args:
        task_name: The name of the task, 任务的名称
        agent_cfg_entry_point: The entry point key to resolve the agent's configuration file, 解析智能体配置文件的入口点
        因为每个深度学习框架的配置文件格式不一样,所以需要通过入口点来解析,如 RSL-RL 入口设置为 rsl_rl_cfg_entry_point。

    Returns:
        The decorated function with the envrionment's and agent's configurations updated from command line arguments.
        返回一个装饰器函数,该函数在调用时会注册任务到Hydra,并从Hydra解析的命令行参数更新环境配置和智能体配置。
    """

    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            # STEP: 1.根据任务名称和智能体配置文件入口点,构建配置类实例,且把配置类实例注册到 Hydra 配置存储中
            # register the task to Hydra, 
            env_cfg, agent_cfg = register_task_to_hydra(task_name, agent_cfg_entry_point)

            # STEP: 2.通过 hydra.main 装饰器装饰 hydra_main 函数,该装饰器的作用是解析命令行参数,
            # STEP:   并更新配置实例对象 env_cfg, agent_cfg 对应的属性
            # define the new Hydra main function
            @hydra.main(config_path=None, config_name=task_name, version_base="1.3")
            
            # STEP: 3. 定义 hydra_main 函数,该函数会对 env_cfg, agent_cfg 配置进行一些处理
            def hydra_main(hydra_env_cfg: DictConfig, env_cfg=env_cfg, agent_cfg=agent_cfg):
                
                # STEP: 3.1 将递归将配置实例对象转换为原始的 Python 容器类型(字典或列表)。
                # convert to a native dictionary
                hydra_env_cfg = OmegaConf.to_container(hydra_env_cfg, resolve=True)
                
                # STEP: 3.2将字符串中的切片对象替换为实际的切片对象,如 "some_key": "slice(0,5,1)" 替换为 slice(0,5,1)
                # replace string with slices because OmegaConf does not support slices
                hydra_env_cfg = replace_strings_with_slices(hydra_env_cfg)
                
                # STEP: 3.3 将 Hydra 解析的命令行参数更新到 env_cfg 
                # update the configs with the Hydra command line arguments
                env_cfg.from_dict(hydra_env_cfg["env"])
                
                # STEP: 3.4 设置观测空间(env_cfg.observation_spaces)、动作空间(env_cfg.action_spaces) 反序构建实例化操作,
                # STEP:     直白的说就是根据字符串反序列化构建实例对象,如 
                # STEP:             env_cfg["action_spaces"]="type:gymnasium", space:Box, low:-1.0, high:1.0, "shape":3" 
                # STEP:     替换为
                # STEP:             env_cfg["action_spaces"] = Box(low=[-1.0], high=[1.0], shape=[3])
                # STEP:     具体参考 source/extensions/omni.isaac.lab/omni/isaac/lab/envs/utils/spaces.py 中的 deserialize_space() 函数
                # this must be done after converting the env configs from dictionary to avoid internal reinterpretations
                env_cfg = replace_strings_with_env_cfg_spaces(env_cfg)
                
                # STEP: 3.5 获取智能体配置参数,然后与 env_cfg 一起传递给 main 函数
                # get agent configs
                if isinstance(agent_cfg, dict) or agent_cfg is None:
                    agent_cfg = hydra_env_cfg["agent"]
                else:
                    agent_cfg.from_dict(hydra_env_cfg["agent"])
                # call the original function
                func(env_cfg, agent_cfg, *args, **kwargs)

            # call the new Hydra main function
            hydra_main()

        return wrapper

    return decorator

关于装饰器的基本介绍这里就略过了,若有兴趣可以自行查阅相关资料。总的来说,main() 函数被 hydr_task_config() 函数装饰之后,其再调用 main() 函数之前会先调用装饰函数 hydr_task_config()。直白的说,就是增加了一个预处理操作,把处理好的数据传递给 main() 函数。不过比较特别的是,其并没有直接调用 main() 函数,而是定义了一个新的函数 hydra_main(),该函数的作用是解析命令行参数,后面再分析。由上源码可以知道 hydr_task_config() 函数第一步工作就是调用了:

   def register_task_to_hydra(
      task_name: str, agent_cfg_entry_point: str
   ) -> tuple[ManagerBasedRLEnvCfg | DirectRLEnvCfg, dict]:
      env_cfg = load_cfg_from_registry(task_name, "env_cfg_entry_point") # 加载环境配置类实例
      agent_cfg = None
      if agent_cfg_entry_point:
         agent_cfg = load_cfg_from_registry(task_name, agent_cfg_entry_point) # 加载智能体配置类实例
      ConfigStore.instance().store(name=task_name, node=cfg_dict) # 注册配置类实例到 Hydra

函数 register_task_to_hydra 具体作用还是比较大的,其会首先根据 task_name 和 agent_cfg_entry_point 返回环境配置以及智能体配置的实例。前者环境配置主要与仿真(isaac-sim)相关,后者智能体配置主要是与强化学习库(比如RSLl_RL)相关。具体细节,本人这里就不展开了,有兴趣的可以自行查阅源码,总的来说,就是构建了 UnitreeGo2RoughEnvCfg 与 UnitreeGo2RoughPPORunnerCfg 这两个配置类实例。注意,这里这是本人的实例,随着训练脚本或任务的不同,这里的配置类实例会有所不同。

另外需要注意到 ConfigStore.instance().store(name=task_name, node=cfg_dict) 这句代码,其是把配置类实例注册到 Hydra 容器中存储,这里的 cfg_dict 包含了环境配置 env_cfg 和智能体配置 agent_cfg,这是比较重要的。

三、Hydra 配置

再讲解 Hydra 配置 之前,还是得回顾一下 Hydra 如何使用,比如说在训练的时候,可以通过如下指令指定训练的环境(智能体数量):

python scripts/reinforcement_learning/rsl_rl/train.py --task Isaac-Velocity-Rough-Unitree-Go2-v0 env.scene.num_envs=32

其中通过 python scripts/reinforcement_learning/rsl_rl/train.py --task Isaac-Velocity-Rough-Unitree-Go2-v0 env.scene.num_envs=32 修改训练时智能体数量,就是使用 Hydra 配置 的具体好处,当然其他的参数全部都是可以修改的,有兴趣的朋友可以自己尝试一下。

回到提到 ConfigStore.instance().store() 会把 env_cfg, agent_cfg 这两个配置类实例注册到 Hydra 容器中存储,接着回到前面的 decorator() 函数,其位于调用 register_task_to_hydra() 函数之后被调用。特别的一点是,该函数又被装饰器函数 @hydra.main() 装饰,其作用是解析命令行参数,并更新存储与 Hydra 容器中的环境配置 env_cfg 以及智能体配置 agent_cfg。剩余的代码有了比较详细的注释,这里就不再赘述了。注意的是:

env_cfg.from_dict(hydra_env_cfg["env"]) 
agent_cfg.from_dict(hydra_env_cfg["agent"])

这两句代码也是比较重要的,因为装饰器函数只会更新存储于 Hydra 中的配置,而不会更新 main() 函数中的 env_cfg 与 agent_cfg,所以需要通过这两句代码把 Hydra 解析的命令行参数更新到 外部的 env_cfg 与 agent_cfg 中,接着其执行了代码:

func(env_cfg, agent_cfg, *args, **kwargs)

这里的 func 就是需要被装饰的 main 函数,比如说再次回到代码 scripts/reinforcement_learning/rsl_rl/train.py 中,找到 main() 函数定义如下:

@hydra_task_config(args_cli.task, "rsl_rl_cfg_entry_point")
def main(env_cfg: ManagerBasedRLEnvCfg | DirectRLEnvCfg | DirectMARLEnvCfg, agent_cfg: RslRlOnPolicyRunnerCfg):
	......

其接收 ManagerBasedRLEnvCfg 类型实例 env_cfg,以及 RslRlOnPolicyRunnerCfg 实例 agent_cfg,与前面讲解过程是意义对应的。

四、结语

通过该篇博客,从源码策层面分析了 isaac-lab 配置文件是如何被解析并加载的,且对 Hydra 配置进行了详解分析,该框架的引入使得训练时可以通过命名行覆盖任意配置文件参数,极大方便了训练者。总的来说,如下部分的分析已经完成。

         4:文件配置是如何加载解析的,如搭建个人项目应该如何进行文件配置? --> 该篇博客
SQL Prompt是Red Gate Software公司开发的一款强大的SQL代码编辑和优化工具,主要面向数据库开发者和管理员。版本11.0.1.16766是一个更新版本,它提供了更高效、更便捷的SQL编写环境,旨在提升SQL代码的可读性、效率和一致性。这个安装包包含了所有必要的组件,用于在用户的计算机上安装SQL Prompt工具。 SQL Prompt的核心功能包括自动完成、智能提示、格化和重构。自动完成功能能够帮助用户快速输入SQL语句,减少键入错误;智能提示则基于上下文提供可能的选项,加快编写速度;格化功能允许用户按照自定义或预设的编码规范对SQL代码进行美化,提升代码的可读性;而重构工具则可以帮助用户优化代码结构,消除潜在问题。 在描述中提到的“代码格化规则来源于网络”,指的是用户可以通过下载网络上的json文件来扩展或定制SQL Prompt的代码格化规则。这些json文件包含了特定的格设置,如缩进风格、空格使用、注释位置等。将这些文件复制到指定的目录(例如:C:\Users\用户名\AppData\Local\Red Gate\SQL Prompt 10\Styles)后,SQL Prompt会读取这些规则并应用到代码格化过程中,使得用户可以根据个人偏好或团队规范调整代码样。 以下几点请注意: 1. 经实测,此版本支持最新的Sql Server 2022版的SSMS21 2. 此安装包中不包括keygen,请自行解决
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

江南才尽,年少无知!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值