You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何继承scipy Rotation类并自定义默认degrees=True的初始化方法

解决scipy Rotation子类默认degrees=True的初始化问题

错误原因

你遇到的循环调用+形状错误,根源在于:子类Rotation的__new__中调用了Rotation.from_rotvec,这里的Rotation是你定义的子类。而scipy的from_rotvec类方法在创建实例时,会调用子类的__new__,导致循环调用——第二次进入__new__时,传入的参数已经是scipy Rotation内部存储的四元数(形状(4,)),完全不符合from_rotvec要求的(3,)或(N,3)输入,因此触发报错。

正确实现

直接在子类__new__中调用父类的from_rotvec方法,避免循环,同时设置默认degrees=True:

import numpy as np
from scipy.spatial.transform import Rotation as ScipyRotation
import numpy.typing as npt

class Rotation(ScipyRotation):
    def __new__(cls, rotation: npt.ArrayLike, *, degrees: bool = True):
        # 调用父类的from_rotvec,绕过子类的__new__循环
        return ScipyRotation.from_rotvec(np.asarray(rotation), degrees=degrees)

# 测试示例
if __name__ == "__main__":
    # 默认degrees=True
    rot1 = Rotation([0, 0, 0])
    print("零旋转四元数:", rot1.as_quat())
    
    # 显式指定degrees=True
    rot2 = Rotation([90, 0, 0], degrees=True)
    print("绕X轴转90度的欧拉角:", rot2.as_euler('xyz', degrees=True))
    
    # 也可以手动指定degrees=False(弧度制)
    rot3 = Rotation([np.pi/2, 0, 0], degrees=False)
    print("绕X轴转π/2弧度的欧拉角:", rot3.as_euler('xyz', degrees=True))

补充说明

  1. 可以删除子类的__init__方法:因为__new__返回的是父类ScipyRotation的实例,子类的__init__不会被执行,留着无意义。
  2. scipy的Rotation是不可变类,实例创建依赖类方法而非直接构造函数,因此重写__new__是最直接的方式,但必须注意调用父类的类方法来避免循环。

内容的提问来源于stack exchange,提问作者Tom McLean

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 15:40:23