开源HSM学习笔记---状态机的运行

原创 2015年07月06日 16:46:23

1、状态机的创建

/************************************
State Table(下面每个状态的parent state需要在create中实现),状态列表中成员信息依次为当前状态id、父母状态id、跳转列表、入口动作、出口动作、行为动作、父母状态

************************************/
static state m_stateList_SampleHSM[MAX_STATEID]=
{
{0,0,0,0,0,0},//STATEID_NULL
{ROOT_STATE,STATEID_NULL,&transitionTable_SampleHSM[ROOT_STATE],0,0,0,0},//ROOT_STATE


{STATE_1,ROOT_STATE,&transitionTable_SampleHSM[STATE_1],State1_Entry,State1_Exit,State1_Do,0},//STATE_1


{STATE1_1,STATE_1,&transitionTable_SampleHSM[STATE1_1],State1_1_entry,State1_1_Exit,0,0},//STATE1_1


{STATE1_2,STATE_1,&transitionTable_SampleHSM[STATE1_2],State1_2_entry,State1_2_exit,State1_2_Do,0},//STATE1_2


{STATE_2,ROOT_STATE,&transitionTable_SampleHSM[STATE_2],State2_entry,State2_exit,0,0},//STATE_2


{STATE2_1,STATE_2,&transitionTable_SampleHSM[STATE2_1],State2_1Entry,State2_1Exit,0,0},//STATE2_1


{STATE2_1_1,STATE2_1,&transitionTable_SampleHSM[STATE2_1_1],State2_1_1_Entry,State2_1_1_Exit,0,0},//STATE2_1_1


{STATE_3,ROOT_STATE,&transitionTable_SampleHSM[STATE_3],State3_Entry,State3_Exit,0,0},//STATE_3


{State4,ROOT_STATE,&transitionTable_SampleHSM[State4],State4Entry,State4Exit,State4_Do,0}//State4
};


用户创建状态机函数
/************************************/
/*!
   \fn void SampleHSM_HSM_Create(void)
*  \brief Creating the HSM
*  \return void
*/
/************************************/
void SampleHSM_HSM_Create(void)
{
 hsm_create(m_stateList_SampleHSM,9);

}


基本创建函数

/*! \fn void hsm_create(state *stateList,unsigned int noOfStates) 
*  \brief This function creates the HSM
*  \param *stateList The pointer to the statelist.
*  \param noOfStates Number of states in the HSM
*  \return void
*/
void hsm_create(state *stateList,unsigned int noOfStates)
{
unsigned int stateID = 0;
unsigned int parentID = 0;
hsm_stateList = stateList;


for (stateID = 0; stateID <= noOfStates ;stateID++)
{
parentID = hsm_stateList[stateID].parentID;
hsm_stateList[stateID].parentState = &hsm_stateList[parentID];    //指定其parent state
//printf(" state = %d  ",hsm_stateList[stateID].stateID);
//printf(" state parent = %d \n ",(hsm_stateList[stateID].parentState)->stateID);


}
if(noOfStates > 0)      //指定初始状态
{
hsm_currentState = &hsm_stateList[STATE_START];//set the current state as the root state. the root state shall be the first state.
}


}



2、状态机的开启

/************************************/
/*!
   \fn void SampleHSM_HSM_Start(void)
*  \brief Starting the HSM
*  \return void
*/
/************************************/
void SampleHSM_HSM_Start(void)
{
 hsm_start();
}



/*! \fn void hsm_start(void) 
*  \brief This function is used to start the HSM. 
*   Here ROOT state enters to the Default child state
*  \param void
*  \return void
*/
void hsm_start(void)
{

//printf(" state before = %d  ",hsm_currentState->stateID);
hsm_onEvent(EV_DEFAULT);


}


激活状态机的触发事件

/*! \fn void hsm_onEvent(EventID eventId) 
*  \brief This function is used to fire events to HSM
*  From here the Event Processing function is called 
*  \param eventId The ID of the Current Event
*  \return void
*/
void hsm_onEvent(EventID eventId)
{
   hsm_ProcessEvent(eventId);
   
}


事件处理流程中,丢一个触发事件进来,当前状态根据该触发事件进行跳转处理,当前状态无法处理触发事件的,则丢给其父母节点进行处理
/*! \fn void hsm_ProcessEvent(EventID eventId) 
*  \brief This function is used to process events fired to HSM
*  First it is found  who will be consuming the event. 
*  If the current state is not consuming the event the parent state is checked for it.
*  If nobody in the state hierarchy consumes the event the function does not perform any action. 
*  if the event consumer state is found state transition is executed.
*  \param eventId The ID of the Current Event
*  \return void
*/
void hsm_ProcessEvent(EventID eventId)
{
/*
*First find who will consume the event. If the current state is not consuming the event find the parent state
* who will be consuming it.If nobody in the state hierarchy consumes it do not perform any action. 
*if the state is found execute the exit and entry action sequence.
定义
#ifndef HSM_RESULT_NOK
#define HSM_RESULT_NOK 0
#endif
首先判断该事件是否能触发当前状态发生跳转,如果不能(result=0(HSM_RESULT_NOK)),在触发事件id不为null(EV_DEFAULT)的情况下,当前状态返回到其父母状态,否则,退出循环;

找到当前状态的跳转,则保存其下一次跳转的状态,并执行跳转动作hsm_doTransition

*/
unsigned int result = HSM_RESULT_NOK;
state * currentStateBackUp = hsm_currentState;
state *currentState = hsm_currentState;
unsigned int transitionID = 0;
while(
!result &&
currentState->stateID != STATEID_NULL
)                                                                                                                                    // 查找当前状态到目的状态的跳转路径
{
result = hsm_isEventConsumed(currentState,eventId,&transitionID) ;//checking if the event is consumed by the state,查找当前状态在触发事件下发生跳转的transitionID是否存在
if(HSM_RESULT_OK == result)
{
#ifdef SYSTEM_SIMULATION
printf(" Event consumed %d\n",eventId);
#endif
}
if(!result && eventId != EV_DEFAULT)
{
currentState = currentState->parentState;//setting the current state to parent state   ,当前状态到目的状态的直接路径不存在,且触发事件存在(表明当前状态无法处理该事件),则退出到当前状态的父母节点,查找该父母节点到目的状态的路径是否存在
}
else if(!result && eventId == EV_DEFAULT)          //跳转路径不存在,则退出循环,后面需要恢复当前状态的值
{
break;
}
else
{
hsm_nextState = &hsm_stateList[currentState->smTransition->transition[transitionID].toState];//setting the next state,找到跳转路径,保存目的状态
//printf(" next state  = %d\n  ",hsm_nextState->stateID);
}
}
if(result)
{


hsm_doTransition(transitionID,currentState);// if the event is consumed by the current state do the transition.       找到跳转路径,则执行状态的跳转处理流程

}
else
{
hsm_currentState = currentStateBackUp;
}


}

判断事件是否能触发状态机发生跳转

/*! \fn void hsm_isEventConsumed(state *currentState, EventID eventId,unsigned int *transitionIndex) 
*  \brief This functionchecks if the evnet is consumed by the state indicated by the currentState param.
*   If the event is consumed by a transition the return value is set to HSM_RESULT_OK and the 
*  *transitionIndex is set to the ID of the Transition consuming the event
*
*  \param[in] *currentState pointer to the current state
*  \param[in]  eventId ID of the current Event to be checked for
*  \param[out] *transitionIndex pointer to transitionIndex ID of the transition to be set by the function
*  where the event is consumed. (Here it is assumed that an event can be consumed by  multiple transitions based on transition condition)
*  \return result can be HSM_RESULT_OK or HSM_RESULT_NOK. If the event is consumed by a transition the return value is set to HSM_RESULT_OK and the 
*  *transitionIndex is set to the ID of the Transition consuming the event
*/
unsigned int hsm_isEventConsumed(state *currentState, EventID eventId,unsigned int *transitionIndex)
{
unsigned int result = HSM_RESULT_NOK;
unsigned int transitionID = 0;
unsigned int transitionCount = currentState->smTransition->transitionCount;    //获取当前状态的允许跳转的次数,一个状态根据不同的触发事件会发生多次跳转到不同的目的状态
for(transitionID = 0;transitionID < transitionCount;transitionID++)
{
if(eventId == currentState->smTransition->transition[transitionID].triggerID)          //找到当前状态满足该触发事件的跳转id----transitionID
{
if(currentState->smTransition->transition[transitionID].condition != 0)//execute the transition condition to know if the conditions are correct.,当前触发事件下,是否满足跳转条件
{
if(currentState->smTransition->transition[transitionID].condition()== HSM_RESULT_OK)
{
*transitionIndex = transitionID;//return the current transition Identifier to event processor      //满足触发条件,返回跳转id给事件处理流程
result = HSM_RESULT_OK;
break;
}
}
else
{
*transitionIndex = transitionID;//return the current transition Identifier to event processor     //满足触发事件,无跳转条件时,直接返回跳转id给事件处理流程
result = HSM_RESULT_OK;
break;
}


}
}
return result;


}


跳转处理

/*! \fn void hsm_doTransition(unsigned int transitionID) 
*  \brief This function actually performs the stateTransition. For the state transition execution,
*   the exit functions corresponding to the current and its parent states(which is not the common parent for source and destination) 
*   are to be executed. and Entry function to be executed in the hierarchy order
*  \param transitionID The Id of the transition that need to be perfoemd by the current State
*  \return void
*/
void hsm_doTransition(unsigned int transitionID,state *currentState)
{


if ( hsm_nextState->stateID!= STATEID_NULL)
{
//call the exit hierarchically
executeExit();                           //出口动作,退出当前状态
//execute the state transition
if(NULL != currentState->smTransition)
{
if(NULL != currentState->smTransition->transition[transitionID].action)
{
  currentState->smTransition->transition[transitionID].action();//assuming only one action is there during transition,执行转换动作
}
}
//call the entry hierarchically ,入口动作,进入目的状态
executeEntry();

//execute state transition action
hsm_currentState = hsm_nextState;//do the state transition to next state ,进入目的状态后,就将目的状态设置为当前状态
hsm_nextState = STATEID_NULL;//change the next State  to NULL ,当前状态更新后,目的状态先初始化
//Call the DO action of the state
if(NULL != hsm_currentState )
{
if(NULL != hsm_currentState->doAction)
{
hsm_currentState->doAction();       //执行最新当前状态(即原来的目的状态)的行为动作
}
}
hsm_ProcessEvent(EV_DEFAULT);      //跳转到事件处理流程,进行状态转换
}

}




调度器学习笔记三:HSM状态机理解

今天心情不错,突然想明白了困扰自己几个月的HSM(层次状态机)问题,“顿悟”的感觉真是舒畅。这也再次证明不够聪明的人(我),应该勤能补拙。废话少说,把自己的体会总结如下。         HSM被称为...
  • wuhenyouyuyouyu
  • wuhenyouyuyouyu
  • 2016年12月08日 19:22
  • 1052

HSM层次状态机实战

HSM层次状态机实战
  • xkarl
  • xkarl
  • 2013年04月18日 14:20
  • 1407

一个通用的有限状态机(FSM)框架

吃饭,睡觉,打豆豆现在要实现一个游戏中的一个NPC的AI, 他只做三件事,吃饭,睡觉,打豆豆,最直接,最简答想到的代码应该是这样。void Update() { if(Hungry) { Ea...
  • qp120291570
  • qp120291570
  • 2016年04月19日 02:08
  • 8371

状态机的实现

现在很多人在利用比较流行的开源游戏引擎cocos2d-x开发游戏,在游戏中免不了使用状态机,这里给大家一种我自认为好的状态机的实现O(∩_∩)O~。 先贴上代码: #ifndef BASEST...
  • mergerly
  • mergerly
  • 2013年10月23日 16:01
  • 1171

状态机实现的三种方法-C语言

1. 参考:http://www.eefocus.com/tagner/blog/15-06/313286_07eac.html 2. 转载:http://kb.cnblogs.com/pa...
  • V__KING__
  • V__KING__
  • 2017年05月12日 15:40
  • 1710

开源hsm代码学习笔记---数据结构的定义

1、hsm中状态之间转换条件包含状态转换的触发事件、条件、动作、初始状态、目的状态  /*! \struct Transition  * state Transition elements  */ t...
  • xiaojuliet
  • xiaojuliet
  • 2015年06月29日 16:48
  • 365

层次状态机的实现 c语言

层次状态机的实现 2006-03-14 15:56:47 分类:   本文讲述层次状态机实现形式中的行为继承。从行为继承与类继承之间的OO类相似来看,一个成功的层次状态机应该...
  • xiaojuliet
  • xiaojuliet
  • 2015年06月24日 16:37
  • 1004

层次状态机

出处:http://xlambda.com/blog/2014/11/04/hierarchical-state-machine/ 计算机程序是写给人看的,只是顺便能运行。 —— 《计算机...
  • wuhenyouyuyouyu
  • wuhenyouyuyouyu
  • 2016年11月30日 14:48
  • 2394

事件驱动框架(二)——状态机

事件驱动框架(二) 说明 本篇接上一篇事件驱动框架之后
  • DFSAE
  • DFSAE
  • 2016年11月01日 13:27
  • 3111

开源HSM学习笔记---状态机的运行

1、状态机的创建 /************************************ State Table(下面每个状态的parent state需要在create中实现) ********...
  • xiaojuliet
  • xiaojuliet
  • 2015年07月06日 16:46
  • 974
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:开源HSM学习笔记---状态机的运行
举报原因:
原因补充:

(最多只允许输入30个字)