Newton 源码与公共 API 编码规范全指南:面向贡献者与评审者的工程准则
Newton 源码与公共 API 编码规范全指南面向贡献者与评审者的工程准则【免费下载链接】newtonAn open-source, GPU-accelerated physics simulation engine built upon NVIDIA Warp, specifically targeting roboticists and simulation researchers.项目地址: https://gitcode.com/GitHub_Trending/newton9/newton本文是 Newton 开源物理仿真引擎基于 NVIDIA Warp 的 GPU 加速仿真框架为贡献者与代码评审者制定的权威源码与公共 API 规范。无论你是要新增一个形状接口、引入新的求解器后端还是评审一个改动公共 API 的 Pull Request本文都能帮助你理解 Newton 的命名空间策略、类型签名约定、文档注释格式与测试纪律并给出可直接对照仓库源码的落地点。规范的适用范围与强制力规范的权威地位CODING_GUIDELINES.rst 是 Newton 贡献者与评审者的权威源码与公共 API 指导文档。它前瞻性地适用于两类代码新写的代码正在被大幅修改的既有代码。规范明确禁止两类行为不得仅为了让既有代码符合规范而要求无关的清理改动不得为了迁就规范而破坏一个已被支持的 API。强制程度的分级语言文档对规则的强制程度使用了 RFC 风格的三个等级词理解它们有助于正确把握评审尺度must必须硬性要求评审不过关即无法合入should应该正常情况下的首选做法但在有充分理由时可以例外may可以允许的选择。与其它文档的分工边界该规范的范围仅限于源码与公共 API 约定仓库贡献流程与 PR 工作流见 CONTRIBUTING.md环境搭建与日常开发操作见 开发指南涉及需求符合度、项目契合度、可评审性与维护负担等通用评审问题由 评审指南 覆盖发布就绪度由 release-audit 工作流评估。即使替代方案更符合本规范破坏性变更仍必须遵循 Newton 的弃用deprecation策略。公共 API 表面Public API Surface每个公共符号只暴露一次每个公共模块都必须定义__all__作为它支持的符号的权威清单。每个公共符号应恰好有一个规范的、有文档的导入路径并且只出现在一个公共模块的__all__中——禁止在多个公共子模块中重复导出同一符号。这一条在仓库中有着直接的落地证据。以顶层 newton/init.py 为例它按core、geometry、sim、submodule APIs四个区块分段组织__all__见第 39、62、101、130 行每个区块通过__all__ [...]累加声明。例如MAXVAL、Axis、AxisType属于 core 区块SDF、Gaussian、Mesh、TetMesh等几何类型属于 geometry 区块而Model、ModelBuilder、State、eval_fk等仿真核心符号则统一收在 sim 区块。各公共子模块同样维护自己的__all__例如 _src/actuators/init.py 与 _src/controllers/init.py。弃用策略保留的兼容性导出是唯一例外这类别名应保留在首选 API 文档之外、标记为已弃用并且只能在规定的弃用期结束后移除。newton._src是内部实现细节Python 仍然允许用户通过其他路径触达实现细节但可触达不等于公共或稳定。newton._src是内部命名空间示例与文档必须通过公共模块导入例如newton.geometry、newton.solvers、newton.sensors。仓库的 solvers.py 展示了这种分层——它是公共入口内部通过from ._src import solvers as _solvers转发并用__getattr__做延迟加载__all__ [*_solvers.__all__, experimental] def __getattr__(name: str): if name not in __all__: raise AttributeError(fmodule {__name__!r} has no attribute {name!r}) from None value getattr(_solvers, name) globals()[name] value return valueAPI 参考文档直接从公共__all__声明生成——每当新增、删除或重命名公共符号或模块时都必须同步走 API 文档流程。命名空间要浅且有意在可发现的顶层命名空间与过深的导入路径之间取得平衡规范给出五条原则newton根命名空间只留给普通仿真工作流中广泛需要的概念。在根层级新增符号需要论证它属于典型用户代码而非某个专门领域。相关类型的家族放入公共子模块即使该家族中某个成员单独看也能放在根层级。专门 API 放入稳定的领域模块如newton.geometry、newton.solvers、newton.viewer。不要仅为归类少数几个名字而增加嵌套层级。额外的层级应代表持久的边界例如后端backend、供应商provider或内聚的实验性子系统。不要用utils这类通用模块替代清晰的领域边界。内部实现newton._src之下的布局可以为了可维护性做深层次组织这些限制针对的是公共导入路径而非内部目录结构。公共导入必须轻量导入newton或轻量公共模块时不得急切初始化可选后端或加载重型、供应商相关的依赖。应在可选依赖与后端边界处使用惰性加载并在把符号分配给公共模块时考虑导入耗时。仓库中 solvers.py 的experimental.coupled就是惰性加载的样板——它通过_LazyCoupledModule在首次访问时才importlib.import_module(._src.solvers.coupled, ...)。显式标记实验性公共 API每个面向用户的实验性 API 都必须在用户可见的公共 docstring 或概念页面中显式标记。该标记是兼容性契约的一部分它必须精确指出可能在不经过正常弃用期就发生变化的模块、类型、可调用对象、参数或模式并同步描述相关限制。实验性命名空间newton.solvers.experimental只用于可以合理放在可选导入路径后面的内聚新子系统不能仅仅为了描述实现成熟度而把既有公共类型挪进实验命名空间。仓库中的实际标注散见于各模块例如 _src/geometry/flags.py 中的.. experimental::指令明确指出该 flag 属于实验性耦合求解器契约sdf_hydroelastic.py 中的 hydroelastic 相关接口同样带实验性标注solvers.py 第 58-65 行则为experimental命名空间统一挂载了.. experimental::docstring。命名Naming优先公共前缀相关公共符号要前缀优先命名让它们在自动补全、文档与搜索中聚类——共享概念放前面特化概念放后面ViewerUSD与ViewerGL对应仓库中的 ViewerUSD 与 ViewerGLSolverMuJoCo与SolverXPBD对应 SolverMuJoCo 与 SolverXPBDIKObjectivePosition与IKObjectiveRotation对应 IKObjectivePosition 与 IKObjectiveRotation函数则如add_shape_sphere()而非add_sphere_shape()。同样的原则适用于属性与参数优先稳定名词 限定词如geom_count而非num_geoms复用公共模型已经确立的术语不要另造同义词。避免过于通用的公共名字公共名字在脱离模块路径出现在生成文档、错误信息或搜索结果中时也应保持可理解。当名字可能指代仿真管线的多个部分时应带上领域或概念家族——例如优先IKObjectivePosition而非PositionObjective。而对于上下文无歧义、且不会被单独重新导出或独立文档化的私有辅助函数则避免冗余前缀。最小化新概念在引入新的公共名词之前先判断既有的 Newton 概念是否已经描述了同样的职责。优先扩展现有概念或组合它们而不是引入Entity、Manager这类模糊抽象。当确实需要新概念时PR 必须解释三点既有术语为什么不准确新概念与既有模型的关系哪个组件负责它的生命周期与职责。类型与签名Types and Signatures保持 API 家族一致新增或修改相关公共类型、方法、函数家族时遵循该家族已建立的词汇与签名结构同一概念用相同的参数名不引入同义词共享参数保持一致的相对顺序操作专属参数可预测地分组家族通用选项在适用时都支持并文档化任何有意省略需要调用时构造的可选对象尤其是可变或运行时拥有的对象用None不要在签名里现场构造。以仓库中的 ModelBuilder.add_shape_sphere 为例它与同家族的add_shape_box、add_shape_capsule、add_shape_cylinder分别位于 builder.py 的 7704、7758、7815 行保持一致的位置参数与关键字参数结构——body是唯一的位置主操作数xform、cfg、as_site、color、opacity、label、custom_attributes等可选项全部走关键字参数def add_shape_sphere( self, body: int, *, xform: Transform | None None, radius: float 1.0, cfg: ShapeConfig | None None, as_site: bool False, color: Vec3 | None None, opacity: float | None None, label: str | None None, custom_attributes: dict[str, Any] | None None, ) - int:既有家族成员是详细先例——不要不核对当前 API 就照抄某个示例签名。封闭类别优先用枚举对新的公共封闭类别取值优先用enum.Enum家族而非模块级常量集合。枚举能提升类型安全、聚合相关取值、产生更清晰的 API 文档。当整数互操作或位标志属于契约的一部分时使用合适的枚举变体如IntEnum、Flag。具体规则整数枚举含NONE哨兵时先定义NONE 0后续真实取值追加在后面保证整数身份稳定该偏好不适用于数值常量、默认值、容差或哨兵受 Warp 代码生成约束在 Warp 于特定代码生成边界原生支持枚举类型之前内核面对的表达保持兼容并在公共 Python 边界做转换不经过规定弃用流程不得替换既有公共常量。仓库中GeoType、JointType、ShapeFlags、BodyFlags等类型见 newton/init.py 的 geometry/sim 区块即采用枚举/标志族的组织方式并同时承载内核友好表示。可选参数用关键字专用keyword-only新公共可调用对象的位置参数区只保留最少、稳定的主操作数集合。带默认值的参数通常应为 keyword-only这样新增选项、重排可选参数都不会破坏既有调用方def create_mesh(vertices, indices, *, normalsNone, uvsNone): ...既有的 Python 惯例可以作为例外理由但把既有位置参数改成 keyword-only 是破坏性变更必须走弃用流程。可复用数学放在正确的层对 Warp 原生类型的一般性有用操作应优先上游提交到 Warp而不是变成 Newton 专属概念。如果 Newton 在 Warp 提供之前就需要该操作优先做私有兼容辅助函数并链接到上游 issue属于 Newton 自己拥有的公共数学操作放在newton.math不要放进大杂烩工具命名空间任何临时的公共辅助函数都视为受支持 API迁移用户到 Warp 时同样要走正常弃用要求。Python 源码约定规范用清单形式给出了 Python 源码层面的硬性约定遵循 PEP 8完全自包含于某个拥有类内部、没有独立公共含义的辅助类或枚举优先做嵌套类/嵌套枚举用PEP 604 联合语法x | None替代typing.OptionalWarp 数组用括号语法标注wp.array[wp.vec3]、wp.array2d[float]、wp.array[Any]不使用圆括号的wp.array(dtype...)形式一维数组用wp.array[X]而非wp.array1d[X]命令行参数用 kebab-case如--use-cuda-graph而非--use_cuda_graph仓库中 kamino 示例如 _src/solvers/kamino/examples/rl/example_rl_bipedal.py 使用argparse.BooleanOptionalAction即遵循此风格避免新增必需依赖强烈优先 Warp、NumPy 或标准库而非新的可选依赖引入必需或可选依赖的 PR必须声明其许可证并核实与 Newton 分发兼容必要时更新许可证元数据与声明未知或未声明的依赖许可证在合入前必须评审。文档与注释Documentation and CommentsGoogle 风格 docstring使用Google 风格 docstring类型放在注解里而不是 docstring 里参数写成Args:下的name: description形式dataclass 字段的 docstring 紧跟在该字段后一行使用最短有用的 Sphinx 交叉引用目标优先公共 API 路径面向用户的文档严禁引用newton._src。仓库中 builder.py 的add_shape_spheredocstring 是标准范例Args:逐条描述body、xform、radius、cfg、as_site、color、opacity、label、custom_attributes并给出Returns:与默认值说明ik_objectives.py 中IKObjectivePosition的 docstring 同样遵循该结构。物理量的 SI 单位公共 API docstring 中物理量必须标注 SI 单位粒子位置Particle positions [m], shape [particle_count, 3].关节相关值用[m or rad]空间力向量用[N, N·m]复合数组按分量描述非物理字段不要加单位示例可见 ik_objectives.pylink_offset: Point in the links local frame [m]、target_positions: Target positions [m], shape [problem_count]。行内注释与文档声明行内注释保持简短只留给非显然的意图、约束或边界情况解释为什么而不是复述代码优先用交叉引用代替长篇重复解释依赖或修改某个文档化声明之前核查其内部交叉引用与外部一手来源对照当前代码验证 Newton 专属行为若来源不可得明确说明这一限制而非假设其支持。测试与仓库约定用unittest不用 pytest。仓库测试全面遵守例如 test_sensor_imu.py 的import unittest且每个测试方法都有三引号 docstring——test_sensor_creation的 docstring 是Test basic sensor creation.以简洁的命令式语句概括被验证的行为需要更多上下文时才在空行后追加 Google 风格正文不要在调用 Warp 数组的.numpy()前立即调用wp.synchronize()或wp.synchronize_device()——.numpy()本身已执行同步的设备到主机拷贝GitHub Actions 按 commit SHA 锁定并保留版本注释actionsha # vX.Y.Z优先使用.github/workflows下已加白名单的哈希SPDX 版权行使用文件首次创建的年份不用日期范围修改既有文件时也不更新年份。公共 API 评审清单评审新增或大幅变更的公共 API 时逐项核对单一规范导出每个公共符号有一个规范导出路径相关__all__已更新命名空间浅而有目的未不必要地添加到newton根命名空间命名聚类名字与其概念家族聚类且在脱离上下文时仍然清晰家族一致性API 家族成员使用一致的词汇、参数分组、选项与安全默认值枚举化在执行边界支持的前提下新的类别化类型使用枚举新名词必要性新公共名词确有必要且所有权清晰keyword-only 可选参数可选参数为 keyword-only除非既有惯例支持位置用法数学归属层可复用的 Warp 原生数学放在合适的归属层兼容性兼容性变更遵循弃用策略并更新生成的 API 文档。机械可检查的规则优先用确定性的 lint 或测试覆盖率来强制代码评审则应聚焦语义与架构判断而不是作为不变量唯一的执行手段。结语Newton 的这份源码与公共 API 规范把稳定的公共表面从自由的内部实现严格区分开来__all__单一导出、浅而有目的命名空间、家族一致的签名、枚举化的类别类型、keyword-only 可选参数、显式的实验性标记与 SI 单位注释共同构成了一个可在 GPU 物理仿真库这种高频迭代场景下长期演进的工程契约。无论你是在 newton/_src/sim/builder.py 里新增一个add_shape_*家族方法还是评审一个新的求解器后端都可以把 CODING_GUIDELINES.rst 与公共 API 评审清单作为合入前的最终检查表。【免费下载链接】newtonAn open-source, GPU-accelerated physics simulation engine built upon NVIDIA Warp, specifically targeting roboticists and simulation researchers.项目地址: https://gitcode.com/GitHub_Trending/newton9/newton创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →