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

如何在Pyomo中实现多智能体路径规划的碰撞避免约束?

解决Pyomo多智能体路径规划中的碰撞避免约束问题

错误原因说明

你遇到的Cannot convert non-constant Pyomo expression (...) to bool错误,是因为Pyomo不允许在约束中直接使用!=或or这类布尔逻辑操作——这些操作会试图将包含变量的Pyomo表达式转换为布尔值,但变量在求解完成前是未知的,无法直接判定真假。必须用线性化技术(比如大M法)来表达碰撞避免的逻辑,或者使用非线性求解器支持的非线性约束。


方案1:引入位置变量+大M线性化约束(推荐)

先优化模型结构,显式定义智能体的位置变量,替代原来的get_x/get_y函数,这样约束更清晰,计算效率更高,再用大M法实现线性化的碰撞避免逻辑。

步骤1:添加位置变量与更新约束

# 1. 定义位置变量,整数域对应网格范围
model.pos_x = po.Var(model.time, model.agents, domain=po.Integers, bounds=(1, 10))
model.pos_y = po.Var(model.time, model.agents, domain=po.Integers, bounds=(1, 10))

# 2. 初始位置约束:t=1时位置等于出生点
def init_pos_x(model, a):
    return model.pos_x[1, a] == model.spawns[a, 1]
model.init_pos_x = po.Constraint(model.agents, rule=init_pos_x)

def init_pos_y(model, a):
    return model.pos_y[1, a] == model.spawns[a, 2]
model.init_pos_y = po.Constraint(model.agents, rule=init_pos_y)

# 3. 位置更新约束:每个时间步的位置由前一步位置+移动量决定
def update_pos_x(model, t, a):
    if t == 1:
        return po.Constraint.Skip
    return model.pos_x[t, a] == model.pos_x[t-1, a] + model.moveRight[t-1, a] - model.moveLeft[t-1, a]
model.update_pos_x = po.Constraint(model.time, model.agents, rule=update_pos_x)

def update_pos_y(model, t, a):
    if t == 1:
        return po.Constraint.Skip
    return model.pos_y[t, a] == model.pos_y[t-1, a] + model.moveDown[t-1, a] - model.moveUp[t-1, a]
model.update_pos_y = po.Constraint(model.time, model.agents, rule=update_pos_y)

步骤2:实现碰撞避免约束(大M法)

引入辅助布尔变量,通过线性约束确保任意两个智能体在同一时间步的x或y坐标至少相差1:

# 大M值取网格最大边长即可(这里网格是10x10,取10)
M = 10

# 辅助布尔变量:z1[t,a,a']=1表示智能体a和a'的x坐标不同;z2表示y坐标不同
model.z1 = po.Var(model.time, model.agents, model.agents, domain=po.Boolean)
model.z2 = po.Var(model.time, model.agents, model.agents, domain=po.Boolean)

# 碰撞避免约束逻辑
def collision_avoidance(model, t, a, a_prime):
    if t == 1 or a >= a_prime:
        return po.Constraint.Skip  # 跳过初始时间和重复的智能体对
    # 约束1:z1=1时,x坐标至少相差1;z1=0时约束自动满足
    cons1 = model.pos_x[t, a] - model.pos_x[t, a_prime] >= 1 - M * (1 - model.z1[t, a, a_prime])
    cons2 = model.pos_x[t, a_prime] - model.pos_x[t, a] >= 1 - M * model.z1[t, a, a_prime]
    # 约束2:z2=1时,y坐标至少相差1;z2=0时约束自动满足
    cons3 = model.pos_y[t, a] - model.pos_y[t, a_prime] >= 1 - M * (1 - model.z2[t, a, a_prime])
    cons4 = model.pos_y[t, a_prime] - model.pos_y[t, a] >= 1 - M * model.z2[t, a, a_prime]
    # 约束3:z1和z2至少有一个为1,即x或y坐标必须错开
    cons5 = model.z1[t, a, a_prime] + model.z2[t, a, a_prime] >= 1
    return [cons1, cons2, cons3, cons4, cons5]
model.collision_cons = po.Constraint(model.time, model.agents, model.agents, rule=collision_avoidance)

方案2:非线性约束(仅适用于非线性求解器)

如果你可以使用支持非线性规划的求解器(比如IPOPT),可以直接用距离约束,无需引入辅助变量:

def collision_avoidance_nonlinear(model, t, a, a_prime):
    if t == 1 or a >= a_prime:
        return po.Constraint.Skip
    # 两个智能体的欧氏距离平方至少为1(即不同位置)
    return (model.pos_x[t,a] - model.pos_x[t,a_prime])**2 + (model.pos_y[t,a] - model.pos_y[t,a_prime])**2 >= 1
model.collision_cons_nonlinear = po.Constraint(model.time, model.agents, model.agents, rule=collision_avoidance_nonlinear)

注意:这种方法求解速度通常比线性化方法慢,且只能用非线性求解器。


补充现有代码的小问题修正

  • 你的代码中params["width"]和params["height"]未定义,建议替换为实际网格边界,比如10或model.width.last();
  • limit_speed约束应确保智能体同一时间步最多向一个方向移动(或不动),示例如下:
    def limit_speed(model, t, a):
        return model.moveRight[t,a] + model.moveLeft[t,a] + model.moveUp[t,a] + model.moveDown[t,a] <= 1
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 23:55:37