一、PDDL是什么
PDDL全称Planning Domain Definition Language,规划领域定义语言,是人工智能自动规划领域的标准化描述语言,1998年由Drew McDermott等人提出,用来统一描述规划问题。
自动规划的核心任务:给定初始状态、目标状态、可执行动作,自动寻找一条动作序列,从初始状态一步步执行到达目标。
PDDL把规划拆成两大部分:
- 领域文件(domain.pddl):描述通用知识、动作模型,和具体场景实例无关。
- 问题文件(problem.pddl):描述这一次规划任务的具体对象、初始状态、目标条件。
类比理解:
domain.pddl = 游戏规则(有哪些动作,动作的前提、效果)
problem.pddl = 这一局游戏的地图、物品、开局情况、通关目标
PDDL有多个版本:PDDL1.2、PDDL2.1(增加时序、持续动作)、PDDL3.0(偏好约束),学习入门一般从PDDL1.2开始,只处理经典的确定性、离散、静态规划问题。
二、PDDL核心语法基础
PDDL是LISP风格的前缀表达式,全部用括号包裹,格式:(关键字 参数...)
2.1 领域文件 domain.pddl
domain文件结构固定:
lisp
(define (domain 领域名)
(:requirements 需求项)
(:predicates 谓词列表)
(:action 动作名
:parameters (?变量1 ?变量2 ...)
:precondition (and 前提条件)
:effect (and 效果)
)
)
- (:requirements) :声明用到的语法特性
常用:
:strips:最基础STRIPS规划(经典入门必写):typing:支持类型定义,给对象分类型:equality:支持判断相等=
- (:predicates 谓词)
谓词用来描述状态命题 ,描述对象之间的关系,返回真/假。
语法:(谓词名 ?参数1 ?参数2)
示例:
(at ?x ?loc)含义:对象x在位置loc
(clear ?block)含义:积木?block上方是空的(积木世界经典谓词)
注意:谓词只定义格式,不定义真假;真假写在problem初始状态里。
- (:action 动作)
动作是规划里唯一能改变世界状态的东西,4个部分:
:parameters:动作的形参,变量以?开头:precondition:前提条件。只有全部为真,动作才能执行:effect:动作执行之后带来的状态变化。- 正向效果:增加谓词(变为true)
- 负向效果:
(not xxx),删除谓词(变为false)
经典STRIPS假设:闭世界假设。不在状态里写明的命题,默认是false。
2.2 问题文件 problem.pddl
problem描述单次任务实例:
lisp
(define (problem 问题名)
(:domain 对应的领域名)
(:objects 对象列表 - 类型)
(:init 初始状态谓词集合)
(:goal (and 目标条件))
)
(:objects):定义本次场景里所有实体对象,可以加类型(:init):初始世界状态,所有成立的谓词(:goal):目标,只要这些谓词全部成立,规划成功。不需要描述世界全部状态,只写需要满足的条件。
三、经典示例:积木世界(Block World)
积木世界是PDDL入门标配例子:桌面上有若干积木,可以堆叠。
动作只有两个:
pickup(?x):拿起积木x,前提:x在桌面、x顶上为空、机械手空手;效果:机械手拿着x,x不在桌面。putdown(?x):放下积木x,前提:机械手拿着x;效果:机械手空手,x放在桌面,x顶上为空。stack(?x ?y):把x堆到y上面unstack(?x ?y):把x从y上面拿起来
domain.pddl 积木领域
lisp
(define (domain block_world)
(:requirements :strips :typing)
(:types block - object)
(:predicates
(on ?x ?y) ; x在y上面
(ontable ?x) ; x放在桌子上
(clear ?x) ; x上方是空的
(holding ?x) ; 机械手拿着x
(handempty) ; 机械手空手
)
(:action unstack
:parameters (?x ?y - block)
:precondition (and (on ?x ?y) (clear ?x) (handempty))
:effect (and (not (on ?x ?y)) (not (handempty)) (holding ?x) (clear ?y))
)
(:action stack
:parameters (?x ?y - block)
:precondition (and (holding ?x) (clear ?y))
:effect (and (on ?x ?y) (not (holding ?x)) (handempty) (not (clear ?y)))
)
(:action pickup
:parameters (?x - block)
:precondition (and (ontable ?x) (clear ?x) (handempty))
:effect (and (not (ontable ?x)) (not (handempty)) (holding ?x))
)
(:action putdown
:parameters (?x - block)
:precondition (and (holding ?x))
:effect (and (ontable ?x) (not (holding ?x)) (handempty) (clear ?x))
)
)
problem.pddl 积木问题实例
场景:2块积木A、B。初始:A在桌面,B在A上面。目标:B放到桌面,A上面空。
lisp
(define (problem block_2problem)
(:domain block_world)
(:objects A B - block)
(:init
(ontable A)
(on B A)
(clear B)
(handempty)
)
(:goal (and
(ontable A)
(ontable B)
(clear A)
))
)
规划器求解结果示例(动作序列)
unstack B A
putdown B
执行过程:
- unstack B A:把B从A拿起。状态变化:机械手拿着B,A变为clear。
- putdown B:放下B到桌面。机械手空手,B在桌上,B上方clear。
达到目标。
规划器:PDDL只是描述语言,本身不能求解。需要外部规划器解析PDDL文件搜索动作序列。常用规划器:FastDownward、Planner4、LAMA。
四、PDDL重要概念
4.1 闭世界假设(Closed World Assumption)
STRIPS/PDDL经典规划默认规则:
在当前状态里没有写出来的谓词,就认为是假 。
例:init里面没有写(holding A),代表机械手没有拿A。
4.2 框架问题(Frame Problem)
框架问题:动作只改变一部分状态,没有在effect里写的谓词,保持不变 。
PDDL自动处理:动作effect只写变化的状态,其余状态默认保留,不用手动写大量不变条件。
这是PDDL很关键的一点,不用描述"不受影响的东西"。
4.3 谓词 vs 函数
- 谓词:返回布尔true/false,描述关系,
(on A B) - PDDL2.1引入函数:可以表示数值,例如
(fuel truck),做数值规划。入门PDDL1.2一般不碰函数。
4.4 条件效果(扩展)
:effect里可以写(when 条件 效果),条件满足才触发效果,属于PDDL扩展特性,入门可以先跳过。
五、PDDL常见踩坑点(学习经常出错)
- 括号匹配错误:LISP语法,括号多一个少一个直接解析失败。写代码一定要成对检查括号。
- 变量必须加
?,对象实体不能加?。?x是变量,A、B是实例。 - precondition写错逻辑:动作前提写错,规划器找不到可行路径。
- 忘记写负效果:只写增加谓词,忘记
(not xxx)删除旧状态,状态会矛盾。
举例:拿起积木后,还保留
handempty,状态同时为handempty和holding A,冲突。
- domain和problem的领域名字不一致,规划器加载失败。
- 谓词名称大小写敏感:有的规划器区分大小写,建议全部小写。
六、PDDL适用场景与局限
✅ 适用场景
机器人任务规划、物流调度、仓库搬运、游戏AI任务规划、应急救援任务编排。
例如:机器人在房间移动,抓取物品,规划任务序列。
❌ 局限性(经典PDDL)
- 经典STRIPS是确定性规划:动作执行一定成功,没有概率、不确定性。现实机器人有失败,要用PPDDL(概率PDDL)扩展。
- 不原生支持连续时间,PDDL2.1的
durative-action才支持持续动作。 - 状态空间爆炸,积木数量多、对象多的时候,规划搜索开销急剧上升。
- 只描述符号层面的逻辑,不处理底层运动学、传感器噪声。
七、PDDL实操工具推荐
- FastDownward:高性能经典规划器,学术最常用。
- PDDL Editor:网页在线PDDL编辑器,支持语法高亮+简单规划求解,新手推荐,不用本地编译。
- Planning.Domains:PDDL标准问题库,大量积木世界、物流、导航公开domain案例。
八、小结
PDDL本质是AI规划领域的建模语言 ,把世界拆成对象、谓词、动作,分离领域知识和具体问题。
domain:通用规则,一次编写,多个problem复用。
problem:单次任务实例,定义对象、初始、目标。
学习路线:掌握STRIPS基础PDDL1.2 → 积木世界练习 → 学习PDDL2.1时序/数值扩展 → 尝试使用FastDownward跑规划任务。