结合B-Human中FSM(有限状态机)这一数学建模方式的运用来深入理解B-Human系统的代码
前言
B-Human中某个角色的行为是由计算机科学领域的知识——有限状态机建立起来的数学模型,在深入理解角色代码之前我们先来理解什么是有限状态机。
何为有限状态机
有限状态机(简称FSM)是表示有限个状态以及在这些状态(state)之间的转移(transition)和动作(action)等行为的数学模型。有限状态机的作用主要是描述对象(B-Human里的nao角色)在它的生命周期内所经历的状态序列(state跳转顺序),以及如何响应来自外界的各种事件(transition的条件及go to到何种state)。在计算机科学中,有限状态机被广泛用于建模应用行为、硬件电路系统设计、软件工程、编译器、网络协议、和计算与语言的研究。
有限状态机的三个特征
1、状态总数(state)是有限的。
2、任一时刻,只处在一种状态之中。
3、某种条件下,会从一种状态转变(transition)到另一种状态。
transition和action的同步进行
从第2和第3特征可以得出关于B-Human角色代码中重要的一点,transition的内容和action的内容是同步进行的,可以理解为在某一state下transition和action中的代码双线程进行。这很好理解,在任何时刻对象只处在一种状态中,且transition内容的重点在于转换的条件,action内容的重点在于此状态下对象的行为,是state下反映客观行为最重要的一部分,在某一状态下对象必然要有行为行动(action),但同时在某一state下对象还会自觉地关注transition的条件,所以transition和action两个部分同时进行。在这一推断基础上更能理解角色代码中多数state下的transition中的转换条件为状态持续时间——state_time。
有限状态机的四部分与底层C++的联系
有限状态机在B-Human中的语法应用主要是option、state、transition、action四个内容。这是在较高层次上来看的,为什么这样说呢?因为在option中的state中的action中的内容的底层实现是用C++来写的,而非是由option、state、transition、action写的,或者按照option——state——action的顺序递推下去后所得的内容仍是由C++实现的,举个例子:option(Keeper)中的state(haveDefended)中的action里的三个option——GetUpEngine();Stand();LookAtBall()再按上述顺序递推下去后将会是用C++实现的函数,注意,这里的三个GetUpEngine();Stand();LookAtBall()不是由C++直接实现的,而是仍由有限状态机的数学建模方式利用state完成的。
option的通俗理解
解释一下option,对于非计算机专业的人来说尽管有一定的计算机语言基础,但是在不了解有限状态机的情况下仍无法深入理解我们较高层次上的option是什么,option可以理解为一个容纳了各种可以彼此跳转状态的循环判断语句,但它又不同于循环判断语句,它双进程的进行transition和action,再通俗一点说option就可以理解为一个函数,当你写好了一个option以后你就可以调用这个option,所以当你写好里一个option以后,你就可以理解它为一个行为函数了。
理解了以上之后如何构建角色代码或者书写行为option
我们一般将一个角色的行为写成一个option,这就相当于C++中的main函数一样,其余的option可以被调用在这个“main函数”中的state里的action里,从上层往下层去构造起某个角色的过程无疑是构造“main函数”框架(确定角色的各个state即确定角色这一对象的有限状态机的图)→构造此有限状态机中state(即图中的节点)的action→往下构造所需的低层option(动作option)→调用B-Human底层的某些参数(比如肢体参数、传感器参数等)来赋值给某些量,即图→节点→节点中的图→节点······→底层。具体如何去做可参考来自2017年的CodeRelease2017.pdf中的一段模板代码,我同样也将列出在下边让大家结合文章更容易理解有限状态机在B-Human中的运用和角色代码的书写。
option ( exampleOption )
{
initial_state ( firstState )
{
transition
{
if ( booleanExpression )
goto secondState ;
else if ( libExample . boolFunction () )
goto thirdState ;
}
action
{
providedRepresentation.value=requiredRepresentation.value * 3;
}
}
state ( secondState )
{
action
{
SecondOption () ;
}
}
state ( thirdState )
{
transition
{
if ( booleanExpression )
goto firstState ;
}
action
{
providedRepresentation.value=RequiredRepresentation::someEnumValue ;
ThirdOption () ;/*调用名为ThirdOption的行为option*/
}
}
option (exampleCommonTransitionSpecialStates )
{
com mon_transition
{
if ( booleanExpression )
goto firstState ;
else if ( booleanExpression )
goto secondState ;
}
initial_state ( firstState )
{
transition
{
if ( booleanExpression )
goto secondState ;
}
action
{
providedRepresentation.value=requiredRepresentation.value * 3;
}
}
state ( secondState )
{
transition
{
if ( action_done || action_aborted )
goto firstState ;
}
action
{
SecondOption () ;/*调用名为SecondOption的行为option*/
}
}
}
option ( SecondOption )
{
initial_state ( firstState )
{
transition
{
if ( boolean_expression )
goto targetState ;
else
goto abortedState ;
}
}
target_state ( targetState )
{
}
aborted_state ( abortedState )
{
}
}
结语
至于写某一动作option时所需要的底层参数就需要大家自己下工夫了,在这里我就不做介绍了。
声明
转载请注明出处,引用请发邮件至903139521@qq.com予以告知,谢谢!