Python调用qpsolvers.solve_qp求解MPC二次规划返回None问题
问题背景
- Matlab环境下开发模型预测控制(MPC)逻辑时,调用内置二次规划求解函数
quadprog求解优化问题,核心调用语句如下:
deltaU = quadprog(H,f,M,gamma)
- 各输入矩阵维度匹配要求:H为30×30矩阵,f为30×1矩阵,M为180×30矩阵,gamma为180×1矩阵,代码在Matlab中运行正常,可返回维度为30×1的正确结果向量。
- 将逻辑迁移到Python环境时,选用
qpsolvers库提供的二次规划求解器实现相同功能,导入依赖代码如下:
import numpy as np import qpsolvers from qpsolvers import solve_qp
- 参照Matlab调用逻辑编写的求解语句为:
sol_qp = solve_qp(H, f, M, gamma)
- 运行后返回结果为
NoneType对象,无法得到预期求解结果。使用官方自带示例测试求解器可正常运行,核对传入矩阵维度与Matlab端完全一致,不存在维度不匹配问题。因字符数限制,无法在正文中粘贴包含完整矩阵定义的全部代码。
排查与解决方法
solve_qp返回None的核心原因是求解器判定当前问题求解失败,Matlab与Python端结果不一致基本是由两个环境下求解器的默认规则、参数要求差异导致,按以下优先级排查即可:
- 修正二次项矩阵H的对称性与正定性
Matlab的quadprog会自动对输入的非对称H矩阵做对称化修正,对轻微奇异的H也会做数值鲁棒性处理;但qpsolvers支持的绝大多数后端求解器,要求输入的二次项矩阵必须是严格对称半正定/正定矩阵,传入非对称、接近奇异的H会直接导致求解失败静默返回None。
传入求解器前先对H做预处理:# 强制对称化 H = 0.5 * (H + H.T) # 叠加极小单位矩阵,避免MPC迭代过程中H出现数值奇异 H += 1e-8 * np.eye(H.shape[0], dtype=np.float64) - 统一约束定义、参数类型与传参方式
- Matlab
quadprog中该调用格式对应的不等式约束为M * deltaU ≤ gamma,qpsolvers中对应约束的参数名是G和h,即约束形式为G @ x ≤ h,使用位置传参很容易因为版本差异出现参数顺序错位,必须显式指定参数名传参。 qpsolvers对输入数组类型敏感,如果传入的是整数型numpy数组,很容易触发后端数值计算错误静默失败,所有矩阵传入前必须转为float64类型,同时一维向量要展平,避免出现维度冗余。- 不要依赖默认求解器后端,显式指定适配MPC场景的OSQP后端(需提前通过
pip install osqp安装),避免因默认后端未安装导致静默返回None。
修正后的调用代码如下:
# 统一转换为浮点型,展平一维向量 f = f.astype(np.float64).flatten() M = M.astype(np.float64) gamma = gamma.astype(np.float64).flatten() # 显式指定参数名与求解器 sol_qp = solve_qp(P=H, q=f, G=M, h=gamma, solver='osqp') - Matlab
- 调整求解容差,打开日志定位问题
Matlabquadprog默认的数值判定容差更宽松,Python端多数求解器默认容差更严格,MPC问题中如果约束边界处于可行域临界点,很容易被误判为无可行解。调用时可以打开求解日志,适当放宽容差:
开启sol_qp = solve_qp( P=H, q=f, G=M, h=gamma, solver='osqp', eps_abs=1e-3, eps_rel=1e-3, verbose=True )verbose=True后,求解器会打印完整迭代过程与错误提示,如果存在约束冲突、矩阵数值异常等问题,会直接输出明确的失败原因,无需盲目排查。
内容的提问来源于stack exchange,提问作者Jorge
相关产品推荐
相关产品推荐

