如何在MathematicalProgram约束中正确计算符号表达式
问题说明
需要在Drake的MathematicalProgram中传入符号表达式作为约束,初始测试代码如下:
x = Variable("x") expression = x**2 prog = MathematicalProgram() v = prog.NewContinuousVariables(1) prog.AddConstraint( lambda a: Evaluate(np.array([expression]), {x: a[0].value()}), lb=np.array([0.0]), ub=np.array([0.0]), vars=v, ) result = Solve(prog)
运行代码触发报错:PyFunctionConstraint: Output must be of scalar type AutoDiffXd. Got float instead.。尝试去掉.value(),改为lambda a: Evaluate(np.array([expression]), {x: a[0]})写法时,又出现参数不兼容的报错,无法正常运行。
报错原因
MathematicalProgram在求解流程中会向约束函数传入三类不同标量类型的输入:
- 浮点型
float:用于初始值校验、数值结果计算 AutoDiffXd:用于自动微分求解约束梯度- 符号
Expression:用于部分求解器的符号推导逻辑
初始代码中手动调用a[0].value()将输入强制转换为float类型,导致自动微分阶段约束输出不是要求的AutoDiffXd类型,触发类型报错。直接传a[0]报错通常是导入的Evaluate方法不匹配,没有使用Drake符号模块自带的支持多类型输入的求值方法。
实现方案
方案1:原生符号约束(推荐)
不需要手动写Python lambda包装,直接通过符号替换将表达式绑定到决策变量后传入约束,Drake会自动处理所有类型兼容、梯度计算逻辑,性能最优:
from pydrake.all import Variable, MathematicalProgram, Solve import numpy as np x = Variable("x") expression = x**2 prog = MathematicalProgram() v = prog.NewContinuousVariables(1) # 替换符号变量为决策变量,直接添加等式约束 prog.AddConstraint(expression.Substitute({x: v[0]}) == 0) result = Solve(prog)
方案2:自定义函数约束
如果需要在约束中加入自定义逻辑,必须保留输入的原始标量类型,不要调用.value()做强制转换,同时确保导入pydrake.symbolic下的Evaluate方法,该方法原生支持float/AutoDiffXd/Expression三类输入:
from pydrake.all import Variable, MathematicalProgram, Solve from pydrake.symbolic import Evaluate import numpy as np x = Variable("x") expression = x**2 prog = MathematicalProgram() v = prog.NewContinuousVariables(1) prog.AddConstraint( lambda a: Evaluate(np.array([expression]), {x: a[0]}), lb=np.array([0.0]), ub=np.array([0.0]), vars=v, ) result = Solve(prog)
注意事项
- 约束函数内不要对传入的决策变量值调用
.value()做强制类型转换,会打断自动微分和符号推导链路 - 优先使用原生符号接口添加约束,避免Python函数调用的额外开销,也不会出现类型匹配问题
内容的提问来源于stack exchange,提问作者Nicholas Pfaff
相关产品推荐
相关产品推荐

