Categories

Tags

Table of Contents

  1. 框架结构
  2. 数据访问
  3. 效果
    1. 属性定义
    2. 谓语定义
    3. 对象定义
    4. 世界状态定义
    5. 行动定义
    6. 方法定义
  4. 总结

框架结构

在对基础概念梳理完毕后,首先需要明确我们需要实现哪些东西,以及它们之间的结构如何。

  • 定义域(Domain)
    • 对象类型定义(Object Type)
      • 如, loaction
    • 属性数据结构定义(Property)
      • 如 ,cannibalNum:int,cannibalNum:int,position:float3
    • 对象定义(Objects)
      • 对象名
      • 对象类型
      • 属性
      • 如 objects = { {name=LocA, type=loaction, properties={missionaryNum = 3,cannibalNum = 3 ,position = (10,0,0)} }, {name=LocB, type=loaction, properties={missionaryNum = 0,cannibalNum = 0 ,position = (-10,0,0)} } }
    • 谓语定义(Predicate)
      • 如 At(?m - missionay ?l - loaction), BoatAt(?l - loaction)
        • ?m 是变量名, -后面是变量类型
    • WorldStates 定义
      • 对象关系
        • BoatAt(LocA)
      • 对象属性
        • locA {missionaryNum = 3,cannibalNum = 3 ,position = (10,0,0)}
    • 任务(Task)
      • 基元任务
        • 任务名
        • 参数列表
        • 前提条件
        • σ 替换表达式
      • 复合任务
        • 任务名
        • 参数列表
        • 方法列表
    • 方法(Method)
      • 方法名
      • 参数列表
      • 前提条件
      • 子任务(subtasks)
      • σ 替换表达式
    • 行动
      • 行动名
      • 参数列表
      • 前提条件
      • 作用效果

数据访问

上面的框架结构同时也描述我们可以编辑哪些数据,然后就如何引用这些数据,例如,在编辑前提条件时,作用效果编辑时。

  • 世界状态
    • 对象关系的引用和编辑
    • 对象的属性引用
  • 条件判断
    • 关系判断(是否存在)
      • 分为两个容器,一个是正字面量,即存在;另一个是负字面量,即不存在
    • 逻辑判断(>,<,>=,<=,==,!=)
      • 右边的变量可扩展,既可以组合多个变量或常量
  • 作用效果
    • 关系的添加或移除
    • 世界状态中的对象属性计算替换
      • a = v1 + v2 ,v1,v2可以是对象属性,变量,或者常量,或者表达式(字符串)
      • a = v1 * v2

效果

属性定义

目前只支持基础数据类型(int,string,bool,float,byte,float3),后面会增加结构体的支持,来封装更多的数据类型 image-center

谓语定义

主要是定义谓语及其参数,用来表达对象间的关系 image-center

对象定义

创建一个对象,并为其添加属性,以及属性的默认值 image-center

世界状态定义

和之前分析的一样,把世界状态分为两类,一个是对象间的关系,另一个是对象属性 image-center

行动定义

image-center

方法定义

参数设置 image-center 替换列表设置 image-center

总结

编辑器的话,可以说大体上完成了,最后只需要进行一些小毛病的处理,以及人性化功能的添加和界面优化。

在开放过程中思考比较多的问题是,如何共享定义域中的数据,以方便每个模块都可以获取,如条件判断,需要获取世界状态中的对象关系和对象属性,定义参数是,想要获取属性类型中定义的属性类型等等,几番折腾后,尝试了各种重构,每个都非常麻烦,最后想到了最简单的方法,静态引用,在打开该定义域时,把它赋给一个全局静态引用,从而任何对象都可以对它进行访问。这只是目前感觉比较轻松的解决方案。

另外,对于条件判断的配置方法,之前想做成点击添加变量的方式,最后觉得这个方法不仅要对变量的类型和值进行配置,还要配置变量之间的运算,如 a > b + c * 5 ,像这样一条判断语句,用这种方法简直作死。所以,最后决定用字符串的方式来自定义表达式,最后这个表达式我们可以自行分析解释处理,不过更有意思的办法,就是结合Lua语言来处理,把Lua作为辅助,或者核心。

不过,有点担心使用Lua后,会不会增加运行开销,因为,以后如果有许多单位进行规划,会不会出现性能上的瓶颈。

重要的是先做出来!才有功夫去慢慢优化,现在别瞎猜。下一步,规划器的开发,也就是核心算法的实现,它是整个HTN框架的处理中心,根据编辑器中配置的数据,以及输入的初始状态,进行任务规划,最终生成解决方案。