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

scipy.integrate.solve_ivp中events参数使用问题:当y位置超过3000m时停止积分触发TypeError报错

解决solve_ivp事件函数触发TypeError的问题

我来帮你理清这个问题的根源,以及怎么正确实现你想要的功能~

错误原因分析

你写的hit_ground函数有个关键问题:当y[1] <= 3000时,函数没有返回任何值,Python会默认返回None。而scipy.integrate.solve_ivp的事件函数要求必须始终返回一个数值类型(整数/浮点数)——它是通过监测返回值的符号变化来判断是否触发事件的,当函数返回None时,程序尝试把它和0做比较,自然就抛出了TypeError: '<=' not supported between instances of 'NoneType' and 'int'的错误。

正确的事件函数写法

要实现“当y位置高于3000m时停止积分”,你需要构造一个连续变化的表达式,让它在y[1] = 3000时等于0,同时通过配置事件的direction参数来指定触发方向。示例代码如下:

def hit_upper_limit(t, y):
    # 当y[1] < 3000时返回负数,等于3000时返回0,大于时返回正数
    return y[1] - 3000

然后在调用solve_ivp时,需要把这个事件配置为终端事件,并指定触发方向:

from scipy.integrate import solve_ivp
from math import radians, cos, sin

# 先定义抛体运动的微分方程(根据你的实际场景调整)
def projectile_dynamics(t, y):
    x, y_pos, v, theta = y
    g = 9.81  # 重力加速度
    dx_dt = v * cos(theta)
    dy_dt = v * sin(theta) - g * t
    dv_dt = 0  # 假设忽略空气阻力,速度大小不变
    dtheta_dt = 0
    return [dx_dt, dy_dt, dv_dt, dtheta_dt]

# 配置事件:terminal=True表示触发时停止积分,direction=1表示只追踪从负到正的符号变化
upper_limit_event = {
    'fun': hit_upper_limit,
    'terminal': True,
    'direction': 1
}

# 初始条件和求解
y0 = [0, 0, 500, radians(45)]
solution = solve_ivp(
    fun=projectile_dynamics,
    t_span=[0, 100],  # 积分时间范围,设置足够大的值
    y0=y0,
    events=upper_limit_event
)

关键说明

  • direction=1:指定只有当事件函数的返回值从负数变为正数时才触发事件,也就是刚好在y位置超过3000m的瞬间停止积分,避免反向情况的误触发。
  • 事件函数必须始终返回数值:这样solve_ivp才能持续监测符号变化,不会出现类型错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 18:02:41