如何在pydrake场景YAML文件中优雅引用本地SDF文件?
解决Drake项目中混用自研与官方SDF文件的路径问题
核心思路
问题本质是Drake的资源加载器默认不识别自研项目的相对路径,同时绝对路径、动态生成YAML的方案都不够优雅,我们可以从扩展Drake资源搜索范围或自定义路径解析两个方向找到更简洁的解法。
可行方案
1. 扩展Drake的资源搜索路径
Drake支持通过环境变量或代码API添加自定义资源目录,让自研SDF可以用类package://的方式引用,同时文件能被Git正常追踪:
- 环境变量方式:启动项目前设置
DRAKE_RESOURCE_ROOT为自研项目根目录,比如在终端执行export DRAKE_RESOURCE_ROOT=/path/to/your/project,之后在YAML里直接用package://relative/path/to/your.sdf引用自研文件,Drake会自动从你设置的根目录查找。 - 代码API方式:在项目初始化代码里调用Drake的路径添加接口,把自研SDF所在目录纳入搜索范围:
完成配置后,YAML里既可以用from pydrake.common import AddResourceSearchPath import os # 获取当前脚本所在的项目根目录(绝对路径) project_root = os.path.abspath(os.path.dirname(__file__)) AddResourceSearchPath(project_root)package://path/to/your.sdf引用自研文件,官方的package://pydrake/manipulation/...引用也不受影响。
2. 给自研项目添加package.xml配置
在自研项目根目录创建一个package.xml(符合ROS包格式,Drake原生支持解析),声明项目的资源根路径:
<?xml version="1.0"?> <package format="2"> <name>your_custom_robot_pkg</name> <version>0.0.1</version> <description>Custom robot SDF resources</description> <export> <drake_resource_root>./</drake_resource_root> </export> </package>
把这个package.xml和自研SDF文件一起提交到Git,之后在YAML里就能用package://your_custom_robot_pkg/path/to/your.sdf引用自研文件,Drake的资源加载器会自动识别这个自定义包。
3. 自定义YAML路径解析逻辑
如果不想修改Drake的资源搜索配置,可以在加载YAML时手动处理相对路径:
- 在YAML里直接写相对路径,比如
file://./sdf/your_robot.sdf - 加载YAML时,基于YAML文件所在目录,把相对路径转换为绝对路径:
import yaml import os def load_scenario_with_relative_paths(yaml_path): yaml_dir = os.path.abspath(os.path.dirname(yaml_path)) with open(yaml_path, 'r') as f: scenario = yaml.safe_load(f) # 遍历场景中的模型引用,替换相对路径 for model in scenario.get('models', []): if 'sdf_file' in model: sdf_path = model['sdf_file'] if sdf_path.startswith('file://./'): relative_path = sdf_path.replace('file://./', '') absolute_path = os.path.join(yaml_dir, relative_path) model['sdf_file'] = f'file://{absolute_path}' return scenario
这种方式下YAML可以保持静态,加载时自动完成路径转换,既不用写死绝对路径,也不用动态生成YAML文件。
方案对比
- 方案1/2更符合Drake的资源加载规范,适合长期维护的正式项目;
- 方案3更灵活,适合快速迭代或不想调整项目结构的场景。
内容的提问来源于stack exchange,提问作者Ittai Rubinstein
相关产品推荐
相关产品推荐

